perm filename SPOOL[COM,LSP] blob
sn#845864 filedate 1987-09-16 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00232 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00035 00002 ∂01-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00037 00003 ∂02-Jun-87 1029 RPG object / cleanup subcommittee interaction
C00039 00004 ∂02-Jun-87 1203 Bobrow.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00041 00005 ∂02-Jun-87 1642 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
C00043 00006 ∂02-Jun-87 2022 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
C00049 00007 ∂03-Jun-87 1220 Bobrow.pa@Xerox.COM Re: Floats
C00053 00008 ∂03-Jun-87 1221 Gregor.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00055 00009 ∂03-Jun-87 1455 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
C00057 00010 ∂03-Jun-87 1709 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00074 00011 ∂03-Jun-87 2020 RPG My Message of May 29
C00077 00012 ∂04-Jun-87 1004 kempf%hplabsc@hplabs.HP.COM SETF- method names
C00080 00013 ∂04-Jun-87 1525 kempf%hplabsc@hplabs.HP.COM Re: object creation / initialization discussion
C00085 00014 ∂05-Jun-87 2359 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00092 00015 ∂06-Jun-87 1219 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
C00099 00016 ∂06-Jun-87 1350 RPG Order of Initialization
C00106 00017 ∂06-Jun-87 1624 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00111 00018 ∂06-Jun-87 1636 RPG Order of Initialization
C00112 00019 ∂08-Jun-87 1907 Bobrow.pa@Xerox.COM Open Issues in 87-002
C00119 00020 ∂09-Jun-87 0719 skeene@STONY-BROOK.SCRC.Symbolics.COM Open Issues in 87-002
C00121 00021 ∂09-Jun-87 0803 kempf%hplabsc@hplabs.HP.COM I. Formal Specification of Gen. Fcn. Invocation
C00128 00022 ∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM II. Formal Specification of Gen. Fcn. Invocation
C00133 00023 ∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM III. Formal Specification of Gen. Fcn. Invocation
C00139 00024 ∂09-Jun-87 0805 kempf%hplabsc@hplabs.HP.COM IV. Formal Specification of Gen. Fcn. Invocation
C00148 00025 ∂09-Jun-87 0854 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00151 00026 ∂09-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
C00160 00027 ∂09-Jun-87 1008 kahn.pa@Xerox.COM Re: Open Issues in 87-002
C00162 00028 ∂09-Jun-87 1035 Bobrow.pa@Xerox.COM Re: Open Issues in 87-002
C00164 00029 ∂09-Jun-87 1050 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
C00166 00030 ∂09-Jun-87 1104 Bobrow.pa@Xerox.COM Re: Order of Initialization
C00170 00031 ∂09-Jun-87 1136 Bobrow.pa@Xerox.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00175 00032 ∂09-Jun-87 1743 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Object creation discussion (at last!)
C00181 00033 ∂09-Jun-87 1819 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
C00186 00034 ∂09-Jun-87 1832 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00189 00035 ∂09-Jun-87 1852 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
C00195 00036 ∂09-Jun-87 1921 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
C00201 00037 ∂09-Jun-87 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM I. Formal Specification of Gen. Fcn. Invocation
C00205 00038 ∂09-Jun-87 2234 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00208 00039 ∂09-Jun-87 2349 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
C00210 00040 ∂10-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00225 00041 ∂10-Jun-87 1006 RPG CLOS Document
C00226 00042 ∂10-Jun-87 1114 skeene@STONY-BROOK.SCRC.Symbolics.COM Concepts chapter on standard type classes
C00234 00043 ∂10-Jun-87 1117 skeene@STONY-BROOK.SCRC.Symbolics.COM Design Rationale section on standard type classes
C00245 00044 ∂10-Jun-87 1412 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: I. Formal Specification of Gen. Fcn. Invocation
C00247 00045 ∂10-Jun-87 1627 Bobrow.pa@Xerox.COM Re: SETF- method names
C00250 00046 ∂10-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation Discussion
C00252 00047 ∂10-Jun-87 2338 RPG
C00256 00048 ∂11-Jun-87 0746 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00258 00049 ∂11-Jun-87 0819 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
C00263 00050 ∂11-Jun-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: SETF- method names
C00268 00051 ∂11-Jun-87 1243 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
C00272 00052 ∂12-Jun-87 1002 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Metaclass Protocol
C00279 00053 ∂12-Jun-87 1204 Bobrow.pa@Xerox.COM Re: Order of Initialization
C00281 00054 ∂15-Jun-87 1118 Gregor.pa@Xerox.COM new new initialization protocol blues
C00289 00055 ∂15-Jun-87 1920 Bobrow.pa@Xerox.COM Re: new new initialization protocol blues
C00294 00056 ∂23-Jun-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation
C00308 00057 ∂24-Jun-87 1045 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation
C00313 00058 ∂24-Jun-87 1155 RPG Request to Moon for Thursday's Discussion
C00314 00059 ∂25-Jun-87 0901 RPG Random Thoughts Concerning Initialization
C00318 00060 ∂02-Jul-87 0911 kempf%hplabsc@hplabs.HP.COM ECOOP Reaction to CLOS
C00322 00061 ∂03-Jul-87 0843 Moon@STONY-BROOK.SCRC.Symbolics.COM ECOOP Reaction to CLOS
C00324 00062 ∂06-Jul-87 1130 RPG ECOOP Reaction
C00329 00063 ∂08-Jul-87 0928 RPG First Try at Terminology
C00343 00064 ∂08-Jul-87 0938 RPG Category Errors
C00346 00065 ∂08-Jul-87 1643 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
C00350 00066 ∂09-Jul-87 1207 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00353 00067 ∂09-Jul-87 1326 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C00360 00068 ∂09-Jul-87 1327 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
C00364 00069 ∂09-Jul-87 1329 kempf%hplabsz@hplabs.HP.COM Re: First Try at Terminology
C00368 00070 ∂09-Jul-87 1333 kempf%hplabsz@hplabs.HP.COM Re: Metaclass Protocol Goals
C00376 00071 ∂09-Jul-87 1355 Kahn.pa@Xerox.COM Re: Category Errors
C00378 00072 ∂09-Jul-87 1431 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
C00381 00073 ∂09-Jul-87 1933 Bobrow.pa@Xerox.COM Re: Metaclass Protocol Goals
C00383 00074 ∂10-Jul-87 1026 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00388 00075 ∂13-Jul-87 1039 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Metaclass Protocol Goals
C00398 00076 ∂15-Jul-87 1000 kempf%hplabsz@hplabs.HP.COM Re: Class redefinition and class-changed.
C00401 00077 ∂16-Jul-87 0752 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00404 00078 ∂22-Jul-87 0639 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
C00411 00079 ∂22-Jul-87 1014 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
C00415 00080 ∂23-Jul-87 1812 Gregor.pa@Xerox.COM initialization meeting notes
C00422 00081 ∂23-Jul-87 1917 Bobrow.pa@Xerox.COM Re: Category Errors
C00424 00082 ∂23-Jul-87 1941 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00427 00083 ∂24-Jul-87 0623 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00430 00084 ∂24-Jul-87 0854 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
C00433 00085 ∂24-Jul-87 1133 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Category Errors
C00437 00086 ∂24-Jul-87 1136 RPG Category Errors
C00441 00087 ∂24-Jul-87 1420 Bobrow.pa@Xerox.COM Re: Category Errors
C00445 00088 ∂24-Jul-87 1421 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00448 00089 ∂24-Jul-87 1427 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
C00451 00090 ∂24-Jul-87 1436 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
C00454 00091 ∂24-Jul-87 1437 Moon@STONY-BROOK.SCRC.Symbolics.COM First Try at Terminology
C00457 00092 ∂24-Jul-87 1459 RPG Category Errors
C00459 00093 ∂24-Jul-87 1645 RPG Class Redefinition
C00463 00094 ∂25-Jul-87 0719 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
C00466 00095 ∂25-Jul-87 0720 Moon@STONY-BROOK.SCRC.Symbolics.COM Class redefinition and class-changed.
C00490 00096 ∂27-Jul-87 0930 kempf%hplabsz@hplabs.HP.COM Re: Class Redefinition
C00492 00097 ∂27-Jul-87 0933 kempf%hplabsz@hplabs.HP.COM Technical corrections in 87-002
C00499 00098 ∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Name That Class
C00501 00099 ∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Redefinition
C00505 00100 ∂27-Jul-87 1046 Bobrow.pa@Xerox.COM Re: Name That Class
C00507 00101 ∂27-Jul-87 1159 RPG Name That Class
C00508 00102 ∂27-Jul-87 1224 RPG Class Redefinition
C00509 00103 ∂27-Jul-87 1700 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class Redefinition
C00517 00104 ∂27-Jul-87 1905 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
C00523 00105 ∂27-Jul-87 2012 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C00548 00106 ∂28-Jul-87 1447 Bobrow.pa@Xerox.COM Re: Category Errors
C00551 00107 ∂28-Jul-87 1527 Bobrow.pa@Xerox.COM Re: Class Redefinition
C00555 00108 ∂28-Jul-87 1550 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
C00560 00109 ∂28-Jul-87 1642 Gregor.pa@Xerox.COM Re: Class Redefinition
C00562 00110 ∂28-Jul-87 1648 Gregor.pa@Xerox.COM Re: Class Redefinition
C00564 00111 ∂28-Jul-87 1751 Bobrow.pa@Xerox.COM Re: initialization meeting notes
C00566 00112 ∂28-Jul-87 1907 Gregor.pa@Xerox.COM Re: initialization meeting notes
C00571 00113 ∂28-Jul-87 1922 Gregor.pa@Xerox.COM Re: Name That Class
C00575 00114 ∂28-Jul-87 2126 RPG Partial Orderings
C00576 00115 ∂29-Jul-87 1025 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Miscellaneous decisions taken or to be taken
C00579 00116 ∂29-Jul-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM updated documentation
C00582 00117 ∂29-Jul-87 1415 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
C00592 00118 ∂30-Jul-87 0021 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
C00620 00119 ∂30-Jul-87 0612 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Miscellaneous decisions taken or to be taken
C00630 00120 ∂30-Jul-87 1306 Bobrow.pa@Xerox.COM Re: Name That Class
C00632 00121 ∂31-Jul-87 0939 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
C00638 00122 ∂31-Jul-87 1110 kempf%hplabsz@hplabs.HP.COM TRACE Proposal (Version 1)
C00649 00123 ∂02-Aug-87 1725 RPG Miscellenia
C00652 00124 ∂03-Aug-87 1656 kempf%hplabsz@hplabs.HP.COM Re: Miscellenia
C00656 00125 ∂04-Aug-87 2243 kempf%hplabsz@hplabs.HP.COM Re: Technical corrections in 87-002
C00662 00126 ∂05-Aug-87 1751 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
C00668 00127 ∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellenia
C00671 00128 ∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM TRACE Proposal (Version 1)
C00677 00129 ∂06-Aug-87 1914 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Name That Class
C00683 00130 ∂06-Aug-87 1929 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C00716 00131 ∂09-Aug-87 1514 Gregor.pa@Xerox.COM Miscellaneous decisions taken or to be taken
C00740 00132 ∂10-Aug-87 1122 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
C00747 00133 ∂10-Aug-87 1145 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Name That Class
C00750 00134 ∂10-Aug-87 1419 kempf%hplabsz@hplabs.HP.COM Re: TRACE Proposal (Version 1)
C00758 00135 ∂11-Aug-87 1504 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
C00772 00136 ∂13-Aug-87 0928 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Name That Class
C00777 00137 ∂17-Aug-87 2133 kempf%hplabsz@hplabs.HP.COM Environments, Naming, and CLOS (was Re: Name that Class)
C00787 00138 ∂18-Aug-87 0820 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Names to Objects and Compiler-environment
C00795 00139 ∂18-Aug-87 1136 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C00806 00140 ∂18-Aug-87 1146 Moon@STONY-BROOK.SCRC.Symbolics.COM Agenda for September meeting
C00812 00141 ∂18-Aug-87 1522 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C00816 00142 ∂18-Aug-87 1534 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
C00820 00143 ∂18-Aug-87 1615 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C00823 00144 ∂18-Aug-87 1707 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ECOOP Reaction to CLOS
C00831 00145 ∂18-Aug-87 1728 Moon@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
C00838 00146 ∂19-Aug-87 0632 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C00841 00147 ∂19-Aug-87 0745 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C00843 00148 ∂19-Aug-87 1020 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C00847 00149 ∂19-Aug-87 1123 skeene@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
C00849 00150 ∂19-Aug-87 1349 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
C00853 00151 ∂19-Aug-87 1455 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Names to Objects and Compiler-environment
C00865 00152 ∂19-Aug-87 1737 Gregor.pa@Xerox.COM meeting place
C00867 00153 ∂19-Aug-87 1830 Moon@STONY-BROOK.SCRC.Symbolics.COM meeting place
C00869 00154 ∂20-Aug-87 0928 Moon@STONY-BROOK.SCRC.Symbolics.COM proposed syntactic cleanups in defmethod
C00882 00155 ∂20-Aug-87 1010 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C00922 00156 ∂20-Aug-87 1525 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
C00927 00157 ∂21-Aug-87 0828 kempf%hplabsz@hplabs.HP.COM Re: proposed syntactic cleanups in defmethod
C00937 00158 ∂22-Aug-87 0004 Masinter.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C00939 00159 ∂22-Aug-87 0033 Masinter.pa@Xerox.COM Re: TRACE Proposal (Version 1)
C00941 00160 ∂22-Aug-87 1837 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
C00944 00161 ∂24-Aug-87 1146 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C00953 00162 ∂24-Aug-87 1254 LGD updated spec on SAIL
C00954 00163 ∂24-Aug-87 1304 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
C00960 00164 ∂24-Aug-87 1644 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: proposed syntactic cleanups in defmethod
C00964 00165 ∂24-Aug-87 1701 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: short form of define-method-combination
C00969 00166 ∂26-Aug-87 1916 Gregor.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C00973 00167 ∂26-Aug-87 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
C00976 00168 ∂27-Aug-87 0952 kempf%hplabsz@hplabs.HP.COM Solutions to Name/Object Mapping for Generic Functions
C00984 00169 ∂27-Aug-87 1656 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Solutions to Name/Object Mapping for Generic Functions
C00988 00170 ∂27-Aug-87 1908 kempf%hplabsz@hplabs.HP.COM Re: Names to Objects and Compiler-environment
C01015 00171 ∂28-Aug-87 0150 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
C01018 00172 ∂28-Aug-87 1912 Moon@STONY-BROOK.SCRC.Symbolics.COM Another try on object creation
C01040 00173 ∂30-Aug-87 1946 RPG Class Precedence List
C01045 00174 ∂30-Aug-87 2009 RPG Miscellaneous decisions taken or to be taken
C01047 00175 ∂30-Aug-87 2017 RPG Agenda
C01049 00176 ∂30-Aug-87 2024 RPG Name That Class!
C01056 00177 ∂30-Aug-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
C01058 00178 ∂31-Aug-87 0802 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
C01062 00179 ∂31-Aug-87 1914 MLY@AI.AI.MIT.EDU RPG's recent typo.
C01063 00180 ∂01-Sep-87 1150 Gregor.pa@Xerox.COM Re: Name That Class!
C01066 00181 ∂01-Sep-87 1258 RPG Name That Class!
C01069 00182 ∂01-Sep-87 1300 RPG Anonymous Generic Function Proposal (Draft 1)
C01073 00183 ∂01-Sep-87 1823 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 1)
C01075 00184 ∂01-Sep-87 2317 RPG Anonymous Generic Function Proposal (Draft 2)
C01080 00185 ∂02-Sep-87 1149 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01082 00186 ∂02-Sep-87 1224 Pavel.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01084 00187 ∂02-Sep-87 1534 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Another try on object creation
C01087 00188 ∂02-Sep-87 2013 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
C01093 00189 ∂03-Sep-87 1414 Bobrow.pa@Xerox.COM Re: Another try on object creation
C01098 00190 ∂03-Sep-87 1705 kempf%hplabsz@hplabs.HP.COM Re: Solutions to Name/Object Mapping for Generic Functions
C01109 00191 ∂03-Sep-87 1838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
C01111 00192 ∂04-Sep-87 1058 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01115 00193 ∂04-Sep-87 1112 Lanning.pa@Xerox.COM WITH-SLOTS, "virtual" slots, and the meta-object protocol
C01118 00194 ∂08-Sep-87 1221 RPG WITH-ADDED-METHODS
C01120 00195 ∂09-Sep-87 1124 Bobrow.pa@Xerox.COM Updating Obsolete Instances
C01127 00196 ∂09-Sep-87 1630 Bobrow.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
C01132 00197 ∂09-Sep-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM User control of the CPL
C01146 00198 ∂10-Sep-87 1101 kempf%hplabsz@hplabs.HP.COM Meeting on Sept. 17-18
C01148 00199 ∂10-Sep-87 1250 Bobrow.pa@Xerox.COM Re: Meeting on Sept. 17-18
C01150 00200 ∂10-Sep-87 2248 kempf%hplabsz@hplabs.HP.COM Trace Proposal (Version 2)
C01164 00201 ∂11-Sep-87 0827 skeene@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01168 00202 ∂11-Sep-87 1023 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
C01172 00203 ∂11-Sep-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
C01176 00204 ∂11-Sep-87 1154 Bobrow.pa@Xerox.COM [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
C01187 00205 ∂11-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
C01198 00206 ∂11-Sep-87 1204 skeene@STONY-BROOK.SCRC.Symbolics.COM proposal for arguments for call-next-method
C01202 00207 ∂11-Sep-87 1314 Bobrow.pa@Xerox.COM Deoptimizing Slot Access
C01207 00208 ∂11-Sep-87 1335 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01210 00209 ∂11-Sep-87 1447 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: User control of the CPL
C01212 00210 ∂11-Sep-87 1641 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Updating Obsolete Instances
C01216 00211 ∂11-Sep-87 1657 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01219 00212 ∂11-Sep-87 2030 Bobrow.pa@Xerox.COM Re: User control of the CPL
C01222 00213 ∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
C01227 00214 ∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01230 00215 ∂11-Sep-87 2058 Bobrow.pa@Xerox.COM Re: short form of define-method-combination
C01235 00216 ∂14-Sep-87 1346 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01238 00217 ∂14-Sep-87 1439 Bobrow.pa@Xerox.COM Uninitialized Slots
C01240 00218 ∂14-Sep-87 1446 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Miscellaneous decisions taken or to be taken
C01243 00219 ∂14-Sep-87 1510 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
C01246 00220 ∂14-Sep-87 1511 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized Slots
C01249 00221 ∂14-Sep-87 1532 kempf%hplabsz@hplabs.HP.COM Re: User control of the CPL
C01259 00222 ∂14-Sep-87 1547 Masinter.pa@Xerox.COM Re: Uninitialized Slots
C01261 00223 ∂14-Sep-87 1642 Bobrow.pa@Xerox.COM Re: Agenda for September meeting
C01264 00224 ∂14-Sep-87 2058 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
C01269 00225 ∂14-Sep-87 2129 Bobrow.pa@Xerox.COM Re: Names to Objects and Compiler-environment
C01273 00226 ∂15-Sep-87 0923 RPG Uninitialized Slots
C01275 00227 ∂15-Sep-87 0935 RPG Proposals
C01276 00228 ∂15-Sep-87 1009 kempf%hplabsz@hplabs.HP.COM Re: Proposals
C01278 00229 ∂15-Sep-87 1356 Bobrow.pa@Xerox.COM Re: Uninitialized Slots
C01281 00230 ∂15-Sep-87 1627 kempf%hplabsz@hplabs.HP.COM Re: Updating Obsolete Instances (and CHANGE-CLASS)
C01286 00231 ∂15-Sep-87 1916 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Another try on object creation
C01290 00232 ∂15-Sep-87 2006 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal (Draft 2)
C01294 ENDMK
C⊗;
∂01-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 1 Jun 87 21:32:30 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 161293; Tue 2-Jun-87 00:32:04 EDT
Date: Tue, 2 Jun 87 00:32 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870602003210.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Does anyone have a list of the issues that we wanted the cleanup
committee to address? I remember something about being able to put
generic functions into function cells, a couple of things about cleaning
up the builtin types, the type FUNCTION, and the thing about &key
argument indicators that aren't keywords. The latter two have been
taken care of, the former two haven't and I'm not sure I remember them
too well. Were there any others?
∂02-Jun-87 1029 RPG object / cleanup subcommittee interaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
I assumed that a generic function was a function and so could appear in
a function cell. Doesn't the Concepts chapter state that
(typep <generic function> 'function) => T
I presume that a generic function is a function under the cleaned-up
definition.
Moon, do you know the date of your message discussing the non-keyword &key
arguments? What are the considerations?
I think there were no other problems except for a recommendation to
design a DEFRECORD facility to replace DEFSTRUCT now that DEFSTRUCT is
sort of obsolete.
-rpg-
∂02-Jun-87 1203 Bobrow.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 12:03:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 JUN 87 11:48:05 PDT
Date: 2 Jun 87 11:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 02 Jun 87
10:29 PDT
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870602-114805-4200@Xerox>
Other cleanup issues:
Making FUNCTION be a genuine type (distinct from CONS)
Making PATH-NAME, HASHARRAY etc be distinct from other types so we can
have a class
(i.e. making these be distinguishable by the type system from an
implementation type e.g. array)
∂02-Jun-87 1642 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 16:41:55 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 2 Jun 87 16:36:27 pdt
Received: by hplabsc ; Tue, 2 Jun 87 16:35:16 pdt
Date: Tue, 2 Jun 87 16:35:16 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706022335.AA00365@hplabsc>
To: Common-Lisp-Object-System@sail.stanford.edu,
Moon@STONY-BROOK.SCRC.Symbolics.COM
Subject: Re: object / cleanup subcommittee interaction
Yes. The need for a LOAD-TIME-EVAL function. Most lisps have this
functionality anyway, to implement #, but it needs to available
from macrogenerated code as well. I use it in COOL and I believe
it is used in CALL-NEXT-METHOD.
Other than that, something like the LET-PSEUDO which we use in
HP Lisp to implement lexical instance variables would make
WITH-SLOTS somewhat cleaner, by not requiring a code walk. The
general idea is to have a symbol macro facility, which allows
forms to be substituted for symbols. Careful study would be
required to determine where in the macroexpand-evaluate loop
to insert expansion of symbol macros, however.
jak
∂02-Jun-87 2022 Bobrow.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Jun 87 20:22:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 JUN 87 20:16:33 PDT
Date: 2 Jun 87 18:37 PDT
From: Bobrow.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Gregor.pa's message of 31 May 87 13:12 PDT
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870602-201633-1444@Xerox>
This message proposes another variant on initialization that has in
common with Gregor's and RPG's that it pushes all initialization into
initialization methods. It is most like Gregor's, but has NO new class
options and no new mechanism for calling generic functions. Its
properties are:
1) Legality checking of make-instance arguments is made an environmental
issue.
2) All :initforms are evaluated (as in Gregor's message);
allocate-instance returns an instance with all the values specified by
:initforms filled in.
3) Default values for initargs are computed a special method
4) Standard initialization methods are :after methods, so that more
specialized methods run after less specialized ones. Initialization of
slots is done in these :after methods.
5) Standard macros can provide convenience for the user and allow hooks
into the environment, and probably optimization. By standard I mean in
the sense of my last message, with a reference implementation.
Here is a cut at a more detailed description:
(defmethod make-instance ((c standard-class) &rest initargs)
(let ((o (allocate-instance c)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o)
(defmethod initial-args ((o standard-object) initargs)
initargs)
Suppose for objects of class position one wanted to have
default-initargs :x with default value (compute-x).
Then one would write a method:
(defmethod initial-args ((o position) initargs)
(call-next-method o
(if (get initargs ':x) initargs
(list* ':x (compute-x) initargs))))
The obvious convenient macro would allow one to write
(defmethod-initial-args position (:x (compute-x) :y (compute-y)...))
Suppose one wanted to have :x set the slot x, and :rho to do something
else. One would write
(defmethod initialize-instance :after
((o position) &key (rho :rho) (g002 :x g0002-p)
&allow-other-keys)
(when g0002-p (setf (slot-value x) g002))
... ; do rho stuff)) )
An obvious macro for supporting this might allow
(defmethod-init-after ((o position) &key (rho :rho)) (:x x ...)
... ;do rho stuff)
where defmethod-init-after inserts the :after, &allow-other-keys, and
the arguments used for the slot-value setting, as well as generating
the code.
Arguemnt checking.
I assume here that the set of legal arguments to intialize-instance are
just those that are explicit in some method of initialize-instance, and
some environmental facility will provide appropriate warnings (very fast
hand waving here).
Optimization
I have also ignored any discussion here of how optimized calls to
make-instance could be managed, but I believe it could be done. (more
fast hand waving).
∂03-Jun-87 1220 Bobrow.pa@Xerox.COM Re: Floats
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 12:20:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 11:01:14 PDT
Date: 3 Jun 87 11:01 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Floats
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 May 87
11:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870603-110114-2066@Xerox>
This problem needs to be solved in several parts:
1) We need a way in CLOS to have more than one name for a particular
class. A class should have at most one primary name, the one it
provides as value of (class-named class). I suggest a function
(set-class-name class name &optional primary-name-p)
This will allow us to add names such as FLOAT-24-32 to SHORT-FLOAT
2) We need a mechanism to go from class descriptions to classes,
something like:
(get-class-from-description superclass-name semantic-description).
It would use system dependent descriptions of classes, and a matching
procedure.
e.g. (get-class-from-description
'FLOAT
(AND (MANTISSA 24 32) (EXPONENT 6 10)))
Classes that need such matching might have a property describing
themselves, and a metaclass that knows how to match descriptions, so the
search could be a recursive tree walk from a super.
3) Methods should be defined on semantic-based classes, e.g.
FLOAT-24-32. The real problem for a user is when he/she defines methods
on two classes with different names, and they turn out to be defined on
the same class. Thus one mthod replaces the other. If each method
defined by defmethod remembered the names under which it were defined,
then an appropriate warning could be issued when a replacement of this
kind happened.
4) This solves the FLOAT problem provided CommonLisp has a reasonable
semantics. I do not claim to understand this at all. If it does not,
then this must be solved separately.
∂03-Jun-87 1221 Gregor.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 12:21:08 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 11:32:13 PDT
Date: 3 Jun 87 11:31 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 2 Jun 87 00:32 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870603-113213-2135@Xerox>
Yes, load-time-eval is, I think an important issue for the cleanup
committee.
I also think that providing constructors and accessors for lexical
environments is important. I don't know what committee that is supposed
to fall under, but it would be good to get it fixed as soon as possible.
As I have said before, I would rather see us do that right than add
symbol macros to the language.
∂03-Jun-87 1455 kempf%hplabsc@hplabs.HP.COM Re: object / cleanup subcommittee interaction
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 14:55:16 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 3 Jun 87 14:54:34 pdt
Received: by hplabsc ; Wed, 3 Jun 87 14:53:08 pdt
Date: Wed, 3 Jun 87 14:53:08 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706032153.AA14903@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: object / cleanup subcommittee interaction
I second Gregor's proposal for providing constructors and accessors
for lexical environments. Environments are underspecified in
CLtL, resulting in confusion in implementation.
∂03-Jun-87 1709 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Jun 87 17:09:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 JUN 87 17:00:29 PDT
Date: 3 Jun 87 17:00 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 31 May 87
16:44 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870603-170029-2690@Xerox>
In this message I address what I think is an important point which Dick
happened to mention in his message. Specifically, its important that
whatever the special purpose mechanisms we might want to include in the
initialization protocol are, it should be possible to implement those
using more primitive CLOS.
Specifically, I will look at initarg -defaulting-. I will show that it
is just a specific instance of a more general problem, and I will show
two different ways that problem can be implemented in CLOS. I will also
show how the kinds of optimizations which are desirable can be
implemented in CLOS.
There is a lot of stuff in this message. A lot of this message is
sample code. I know that makes it somewhat dense and I apologize, but I
think the points are important. I hope that at least the following come
across:
- two different ways of thinking about how default initarg inheritance
works.
- how to implement functionality like default initarg inheritance in
CLOS.
- some more examples of the kinds of things the meta-object protocol
is good for.
Initarg defaulting is just a specific instance of the more general
problem of computing a value for a class from component values provided
by all the classes in the class precedence list. Seen as such, there
are two different mechanisms for doing this in CLOS. I will call these
the "structural" and the "procedural" point of view.
In these sample implementations, I will just implement the collection of
the default initargs for a class. These implementations do not take
care of merging the initargs provided in the call to make-instance with
the default values to get the 'total, defaulted, evaluated initargs'.
In a separate message Danny or I will show an interesting way to do that
using the procedural implementation.
In all examples, assume the following class structure, with the
per-class default-initargs as annotated:
menu ((:highlighting :invert)
\ (:expose-near *default-expose-near*))
\
\
color-menu ((:highlighting *highlight-color*))
\
\
editor-menu ((:expose-near *editor-window*))
so that the value returned by
(class-default-initargs (class-named 'editor-menu))
should be
((:expose-near *editor-window*) (:highlighting *highlight-color*))
PROCEDURAL IMPLEMENTATION:
;;;
;;; For each class, define a method on class-default-initargs which
contributes
;;; that class's initargs. The structure is that the initargs for a
particular
;;; class get consed onto the initargs for its superclasses (using
list*). The
;;; primary method on OBJECT provides the NIL for the base of the
consing. The
;;; :around method on OBJECT provides mechanism for removing duplicated
initargs
;;; from the rest of the list.
;;;
(defmethod default-initargs ((c object))
())
(defmethod default-initargs :around ((c object))
(remove-duplicates-from-plist (call-next-method) :from-end 't))
;;;
;;; Here are the methods for the sample classes.
;;;
(defmethod default-initargs ((c menu))
(list* '(:highlighting :invert)
'(:expose-near *default-expose-near*)
(call-next-method)))
(defmethod default-initargs ((c color-menu))
(list* '(:highlighting *highlight-color*)
(call-next-method)))
(defmethod default-initargs ((c editor-menu))
(list* '(:expose-near *editor-window*)))
STRUCTURAL IMPLEMENTATION:
;;;
;;; For classes, define a new class option, :default-initargs, which is
used to
;;; specify the default initargs for that class. The
class-default-initargs
;;; generic function just goes and collects the contributions from all
the
;;; classes merges them together.
;;;
(defclass my-standard-class (standard-class)
((local-default-initargs :initform ()
:accessor class-local-default-initargs)))
;;;
;;; Any class which isn't an instance of my-standard-class has local
default
;;; initargs of (). It is an error to try and set the local default
initargs
;;; of a class which isn't an instance of my-standard-class.
;;;
(defmethod class-local-default-initargs ((class standard-class))
())
(defmethod-setf class-local-default-initargs ((class standard-class))
(nv)
(error "can't set the default initargs of ~S". class))
(defmethod legal-class-option-p ((class my-standard-class) option)
(eq option ':default-initargs))
(defmethod update-class ((class my-standard-class) &key options
&allow-other-keys)
(setf (class-local-default-initargs class)
(getf options :default-initargs))
(call-next-method))
(defun class-default-initargs (class)
(remove-plist-duplicates
(apply #'append
(mapcar #'class-local-default-initargs
(class-precedence-list class))))
:from-end 't))
An obvious problem with both of these implementations is that every time
the class-default-initargs function is called the value is consed up.
Certainly in initialization we would want to be able to optimize this by
caching the result, and it is reasonable to expect that much user code
might want to do so as well. This is also easy to do using CLOS.
PROCEDURAL IMPLEMENTATION (cached version):
In this implementation, in order to make things more simple, we use a
special macro define-default-initargs-method to define the special kinds
of methods on default-initargs. This special macro isn't absolutely
necessary, it just makes the code presented here a little simpler.
(defclass default-initargs-method (standard-method)
((initargs :initform nil
:accessor method-initargs)))
(defmacro define-default-initargs-method (class-name initargs)
`(define-default-initargs-method-1 ',class-name
',initargs
#'(lambda (ignore) ',initargs)))
(defun define-default-initargs-method-1 (class-name initargs fn)
(let* ((class (class-named class-name))
(specs (list class))
(old (get-method #'default-initargs () (list (class-named
class-name)) ()))
(new (make-instance 'default-initargs-method :function fn
:specializers
specs
:initargs
initargs)))
(when old (remove-method #'default-initargs old))
(add-method #'default-initargs new)))
(defgeneric-options default-initargs (class))
;;;
;;; add a method to compute effective method for default-initargs which
will take care of
;;; producing a special effective method when all the methods are of the
special kind.
;;;
;;; if there are any methods on default-initargs that were defined with
defmethod, we will
;;; just revert to ordinary standard method combination. In this way,
we get the optimization
;;; when we can have it, but when someone wants to put a method on
default-initargs that needs
;;; to compute that will work just fine.
;;;
(add-named-method 'compute-effective-method
'(gfun methods type args)
`(',#'default-initargs)
#'(lambda (gfun methods ignore ignore)
(if (every #'(lambda (m) (typep m
'default-initargs-method))
methods)
<make optimized method>
(call-next-method))))
Where <make-optimized-method> produces a method which just has all the
constants collected up in it.
STRUCTURAL IMPLEMENTATION (cached version):
For the structural implementation, much of the code is the same. We
just use the propagate-class-update generic function to maintain a cache
of the proper value. Note that this implementation is not the best
possible. In particular, it recomputes the class-default-initargs
anytime any aspect of a class changes. This is not hard to fix, I have
just done the simplest of the caching implementations here. The reason
being that a more spohisticated structural caching implementations would
have the same structure, it would hook itself into the class update
protocol the same way, but it would be harder to read.
;;;
;;; For classes, define a new class option, :default-initargs, which is
used to
;;; specify the default initargs for that class. The
class-default-initargs
;;; generic function just goes and collects the contributions from all
the
;;; classes merges them together.
;;;
(defclass my-standard-class (standard-class)
((local-default-initargs
:initform ()
:accessor class-local-default-initargs))
(default-initargs
:initform ()
:reader class-default-initargs)))
;;;
;;; A class which isn't an instance of my-standard-class has local and
total
;;; default initargs of (). It is an error to try and set the local
default
;;; initargs of a class which isn't an instance of my-standard-class.
;;;
(defmethod class-local-default-initargs ((class standard-class))
())
(defmethod-setf class-local-default-initargs ((class standard-class))
(nv)
(error "can't set the default initargs of ~S". class))
(defmethod class-default-initargs ((class standard-class))
())
(defmethod legal-class-option-p ((class my-standard-class) option)
(eq option ':default-initargs))
(defmethod update-class ((class my-standard-class) &key options
&allow-other-keys)
(setf (class-local-default-initargs class)
(getf options :default-initargs))
(call-next-method))
(defmethod propagate-class-update ((class my-standard-class)
new-fully-defined-p
old-fully-defined-p
changed-class
&allow-other-keys)
(setf (class-default-initargs class)
(compute-default-initargs class)))
(defun compute-default-initargs (class)
(remove-plist-duplicates
(apply #'append
(mapcar #'class-local-default-initargs
(class-precedence-list class))))
:from-end 't))
∂03-Jun-87 2020 RPG My Message of May 29
To: common-lisp-object-system@SAIL.STANFORD.EDU
In that message I tried to get peoples' attention so that I would make
sure that we did not go too far down the path of something I suspect is an
ad hoc solution to the initialization problem. The point that Gregor
characterizes as something I ``happened to say'' was the main point I was
trying to make - that message was 9 days in the making. In order to get
peoples' attention I used the inflammatory phrasing that solving this
problem in this way would cause me to withdraw my support of CLOS.
Upon reflection, that was a mistake - of course I'm not going to withdraw
my support. I flew off the handle because I think that we have put
together a pretty darn good language with CLOS so far (though it's not
perfect), and I want to make sure we live up to the standards we have set
for ourselves with the work we do to complete it.
It might turn out that Moon's proposed solution is the correct one,
but I want us to explore the alternatives and make sure that there
isn't a whole category of programs we are making hard to write by
not looking at those alternatives now.
You all know that I tend to be outrageous at times, and I do it as part of
the rhetorical game. But I think you all know I've only insisted on one
stupid thing in CLOS so far (the name DEFGENERIC-OPTIONS), so the bluster
cannot mean all that much.
Please accept my apologies and let's get on with the thinking!
-rpg-
∂04-Jun-87 1004 kempf%hplabsc@hplabs.HP.COM SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Jun 87 10:03:40 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 4 Jun 87 10:03:07 pdt
Received: by hplabsc ; Thu, 4 Jun 87 10:02:01 pdt
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706041702.AA04950@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: SETF- method names
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference. However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
jak
∂04-Jun-87 1525 kempf%hplabsc@hplabs.HP.COM Re: object creation / initialization discussion
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Jun 87 15:25:33 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 4 Jun 87 15:25:31 pdt
Received: by hplabsc ; Thu, 4 Jun 87 15:24:22 pdt
Date: Thu, 4 Jun 87 15:24:22 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706042224.AA09308@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: object creation / initialization discussion
I've hesitated to jump into the brouhaha until I had a chance
to review correspondence, and will limit myself to some general
comments, since I think most points of view have been covered.
In particular, I like Dick's analysis, stressing use of features
in the existing CLOS design rather than addition of new, more
complicated features. It does lead to more verbose code for
more complicated applications, thus some applications programmers
will complain, but the simple cases don't require as much conceptual
overhead. The analysis of positional v.s. named arguments in
Common Lisp was interesting. Dick seems to have identified a hole
in the Common Lisp design, which, if correctly filled, could
lead to some simplifications.
His analysis did not touch on order of :INITFORM evaluation, nor
the lexical and dynamic context in which :INITFORM evaluation
occurs. A simple selection of context here would be the lexical
context of the class (as suggested by Danny in an earlier message)
and the dynamic context of one of the methods during MAKE-INSTANCE
invocation. Perhaps the dynamic context could be within MAKE-INSTANCE,
or the ALLOCATE-INSTANCE method, as suggested by Gregor? As for order of
evaluation, perhaps this could be determined by the class precedence
list ordering, for inherited slots, and by lexical ordering within
the DEFCLASS form.
As the 87-002 spec currently stands, the :INITFORM initialization
forms have no reference to previously initialized slots in the
object being initialized, nor can they reference the object being
initialized itself. Dick's proposal seems to imply that the INITIALIZE-INSTANCE
method would be the place for initializations dependent on values
of slots previously initialized to be put. This seems fine with
me. However, I think specifying the order and context of :INITFORM
evaluation is important, for those applications programmers who
feel a need to use side-effects during initialization (however
henious we might find it). If the order and context is not
specified, it will be left up to each implementor to select it,
and thus this aspect of the semantics of initialization will be
determined by the particular implementation rather than the specification.
jak
∂05-Jun-87 2359 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Jun 87 23:59:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 JUN 87 23:49:40 PDT
Date: 5 Jun 87 23:49 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 2 Jun 87 11:48 PDT
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870605-234940-2970@Xerox>
The cleanup committee is considering proposals for function-type and
non-keyword &Key arguments.
There is no proposal yet submitted for PATHNAME-HASH-TABLE-TYPE-DISTINCT
( making pathname, hash-table separate classes.)
There is no proposal yet submitted for SHARP-COMMA-SPECIAL-FORM.
(load time evaluation function. )
There is no proposal yet submitted for DEFSTRUCT-CLOS.
There is no proposal yet submitted for LEXICAL-ENVIRONMENT-ACCESSORS.
A draft of the proposal format is enclosed. Several proposals were
released last X3J13. Stay tuned to X3J13@Sail.stanford.edu for more
samples...
!
Format for proposals to "clean up" Common Lisp.
Version 10 - 5-Jun-87
Replace the text below in >> double inverted angle-brackets <<. Be
brief; leave testimonials and personal opinions to the discussion at the
end. Be complete; do not expect someone else to fix or redesign parts.
Spell out names (e.g., Masinter rather than LMM) and upcase all Lisp
symbols (DEFUN rather than Defun). I like it better if you write in the
third person rather than first.
Issue: >>A short descriptive label, which starts with a name which
occurs in the index of CLtL, and be a suitable symbol in the Common Lisp
style, e.g., CDR-TERMINATION. .<<
References: >>The pages of CLtL which describe the feature being
discussed, or other references..<<
Category: >>One or more of: CLARIFICATION -- proposal to resolve an
ambiguity or case of under-specified situation in CLtL, where this
ambiguity interferes with portability of code. CHANGE -- proposal for an
incompatible change to the language. ADDITION -- proposal for a
compatible extension to the language. <<
Edit history: >>Author and date of submission (version 1), and author
and date of subsequent versions.<<
Problem description: >>Describe the problem being addressed -- why is
the current situation unclear or unsatisfactory? Avoid describing the
proposal here or arguing for its adoption. <<
Proposal (>>issue-label:proposal-label<<): >> Describe as precisely as
possible what you are proposing. Ideally, this should take the form of
text that could be dropped into CLtL or some new specification document.
If necessary, propose a set of labelled alternatives here, rather than a
single proposal. Each proposal must be a complete design; do not leave
out details. Avoid arguing for the proposal here, just describe it.<<
Test Case: >>When possible, give a sample of Common Lisp code that
illustrates the issue.<<
Rationale: >> A brief argument for the proposal. (If more than one
proposal is listed, discuss each issue separately here and in subsequent
sections.)<<
Current practice: >>Do some/many/no Common Lisp implementations already
work this way? Survey independent Common Lisp implementations -
preferably three or more.<<
Adoption Cost: >>What is the cost to implementors of adopting the
proposal? How much implementation effort is required? Is public-domain
code available? For pervasive changes, can the conversion be
automated?<<
Cost of non-adoption: >>How serious is it if nothing is done? <<
Benefits: >>What is better if the proposal is adopted? How serious is
the problem if just left as it is? <<
Conversion Cost: >>For incompatible changes, what is the cost to users
of converting existing user code? To what extent can the process be
automated? How?<<
Esthetics: >>How does this proposal affect the simplicity of the
language, ease of learning, etc.<<
Discussion: >> Additional arguments, discussions, endorsements,
testimonials, etc. should go here. A blow-by-blow account of debates is
not necessary. <<
∂06-Jun-87 1219 Gregor.pa@Xerox.COM Re: Object creation discussion (at last!)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 6 Jun 87 12:18:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 06 JUN 87 12:18:29 PDT
Date: 6 Jun 87 12:18 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Object creation discussion (at last!)
In-reply-to: Bobrow.pa's message of 2 Jun 87 18:37 PDT
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870606-121829-3209@Xerox>
Let me take a stab at simplifying part of Danny's message. Danny is
proposing that the entire initialization protocol be defined in a
procedural way, using methods that the user defines on specific generic
functions. In particular, Danny is going one step farther than a couple
of the messages that I sent out in that he is proposing that initarg
defaulting and initarg declaration be done procedurally. Originally, I
was only proposing that initarg specification be done procedurally.
I didn't really like this proposal when I first heard it, but I like it
a lot now after thinking about it for a bit more. This message sketches
out in a bit more detail what it would be like:
initarg DEFAULTING.
There are two generic functions involved. class-default-initargs and
merge-initargs.
CLASS-DEFAULT-INITARGS, returns the default-initargs for a given class.
It is the collection of the initargs for all the superclasses inherited
in the obvious way. The class-default-initargs generic function uses
standard method combination. There are two pre-defined methods on
class-default-initargs, these are as described in a message I sent out
earlier in the week:
(defmethod default-initargs ((c object))
())
(defmethod default-initargs :around ((c object))
(remove-duplicates-from-plist (call-next-method) :from-end 't))
Given these methods, a user can define default initargs for a particular
class using methods like the following (also from my message of last
week):
(defmethod default-initargs ((c menu))
(list* '(:highlighting :invert)
'(:expose-near *default-expose-near*)
(call-next-method)))
(defmethod default-initargs ((c color-menu))
(list* '(:highlighting ':red)
(call-next-method)))
MERGE-INITARGS takes the class, the supplied initargs and the default
initargs. It merges the supplied initargs with the default initargs and
returns a complete set of defaulted initargs with the values from the
default initargs evaluated. This value is all set to be passed to the
initialize-instance and allocate-instance generic functions. The
default implementation of this generic function is something like:
(defmethod merge-initargs ((class object) supplied default)
(let ((total nil))
(do-initargs (name val default)
(unless (getf name supplied)
(push name total)
(push (eval val) total)))
(append supplied (reverse total))))
As I showed in my message of last week, its really easy to optimize all
this to run just as fast as constructors do now, so speed is not an
issue here.
Some of the reasons I like this are:
It builds on existing mechanism, people can understand it without
having to understand new mechanism.
Because it builds on documented, primitive mechanism, people can
tailor it new ways. Specifically, if for a certain class, the presence
of a particular initarg means that several default initargs should not
be included in the merge, it is easy for someone to figure out how to do
that. They just define their own method on merge-initargs which
implements that rule.
initarg DECLARATION is real simple.
There is one pre-defined method on class-legal-initargs
(defmethod class-legal-initargs ((class object))
())
Users define methods like:
(defmethod class-legal-initargs ((class plane))
(list* ':speed ':engines (call-next-method)))
If a user wants to explicity override some initargs provided by a
superclass they can do that since everything is procedural and under
their control:
(defmethod class-legal-initargs ((class boat))
(let ((supers (call-next-method)))
(list* ':speed (remove :color supers))))
∂06-Jun-87 1350 RPG Order of Initialization
To: common-lisp-object-system@SAIL.STANFORD.EDU
I thought that we have already specified that the INITFORMs happen
in the lexical context within which the DEFCLASS occurred. If there are
specials in the INITFORMs, I suppose that the dynamic context in which
the MAKE-INSTANCE is evaluated provides the dynamic context.
In terms of the order of evaluation of the INITFORMs, I thought that
the inheritance rules we had for slot descriptions settled which INITFORM
was evaluated to provide the initial value for the slot.
In terms of the order of evaluation of the INITIALIZE-INSTANCE methods, it
always seemed to me that method combination was how we should control
that, but that the most sensible default order was most general to most
specific (that is, like :AFTER).
There are, of course, problems with my &required-key proposal. One is that
unless there is some way to not pass all of the optional arguments, there
is no way to have a function with both required keyword and truly optional
positional arguments.
Suppose someone writes
(defun f (x y &optional a b &key foo bar baz ola)
(list x y a b foo bar baz ola))
and this form is evaluated:
(f <a1> <a2> <a3> <a4> <a5> <a6> <a7> <a8>)
The binding of the variables in the function definition goes like this:
x is bound to <a1>, y is bound to <a2>, a is bound to <a3>, and b is
bound to <a4>. Now we lift our heads from the sand and look at what
<a5> is. It should be one of :foo, :bar, :baz, or :ola. Now suppose
we had written:
(f 1 2 :foo 4 :bar 5 :baz 6)
Did the user intend for a to be bound to :foo, or did he intend for
a and b to not be supplied?
Here is my proposal for lambda expressions; it includes Moon's
proposal for non-keyword package symbols to be names of arguments:
(lambda ({var}*
[&optional {var | (var [initform [svar]])}*]
[&required-key {name}*]
[&rest var]
[&key {var | (name var)} [initform [svar]])}*
[&allow-other-keys]]
[&aux {var | (var [initform])}*])
{declaration | documentation-string}*
{form}*)
where var, initform, svar are exactly as before, and name is the name of
a keyword argument, which can be a symbol in any package. Parsing an
argument list proceeds as follows:
Let nrp be the number of required positional parameters. The first nrp
supplied arguments are paired with the nrp required positional parameters.
The remaining supplied arguments are scanned left-to-right, starting with
scanning for positional optionals. If a supplied argument is EQ to one of
the required named parameters, the scanning for positional optionals ends
and all unpaired positional optionals are defaulted according to the
lambda-list specification; then named parameter parsing begins. If a
supplied argument is not EQ to any required named parameter, it is paired
with the next positional optional parameter.
Once the scanning for optional positional parameters has ended, scanning
for named parameters begins. Named parameter parsing is as in current
Common Lisp, except that if, at the end, there are unsupplied
required named arguments, an error is signaled.
The difference between this parsing algorithm and the current Common Lisp
one is that the occurrence of the first required named parameter stops
parsing of positional optionals. Therefore, the only way to pass the name
of required named parameter is as a required positional or required named
argument. Also, if optional named arguments appear to the left of all
required named arguments, they can be taken as positional optionals.
Examples:
(defun f (x y &optional a b &required-key :foo :bar &key baz ola)
(list x y a b foo bar baz ola))
(f 1 2 3 4 :foo 5 :bar 6 :baz 7 :ola 8)
=> (1 2 3 4 5 6 7 8)
(f 1 2 3 :bar 4 :baz 5 :foo 6 :ola 7)
=> (1 2 3 nil 6 4 5 7)
(f 1 2 :baz 3 :foo 4 :bar 5)
=> (1 2 :baz 3 4 5 nil nil)
(f 1 2 :baz :foo 3 :bar 4)
=> (1 2 :baz nil 3 4 nil nil)
Because of Moon's proposal to not require keywords to be in the keyword
package, this proposal introduces some ugliness, but it uses the well-used
design principle: feel free to introduce ugliness and inconsistency for
new users in order to keep old code working.
-rpg-
∂06-Jun-87 1624 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 6 Jun 87 16:24:20 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Sat, 6 Jun 87 14:27:50 pdt
Received: by hplabsc ; Sat, 6 Jun 87 14:26:48 pdt
Date: Sat, 6 Jun 87 14:26:48 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706062126.AA01592@hplabsc>
To: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Order of Initialization
>
>I thought that we have already specified that the INITFORMs happen
>in the lexical context within which the DEFCLASS occurred. If there are
>specials in the INITFORMs, I suppose that the dynamic context in which
>the MAKE-INSTANCE is evaluated provides the dynamic context.
>
This sounds fine with me. I didn't remember a decision being reached
on the lexical part. The dynamic context of MAKE-INSTANCE is OK, presumably
just before the INITIALIZE-INSTANCE method is called and just after
ALLOCATE-INSTANCE? Otherwise, either the instance doesn't yet exist,
or the user could have done some potential customized initialization
which would be overwritten.
>In terms of the order of evaluation of the INITFORMs, I thought that
>the inheritance rules we had for slot descriptions settled which INITFORM
>was evaluated to provide the initial value for the slot.
My reading of the 87-002 document is that the initialization form
which is run for a particular slot is the first one which is encountered,
searching up the class precedence list. This says nothing, however, about
the order in which the initialization forms for all the slots are run.
This is what I meant. I would suggest that the lexical ordering of
slots within a class determine the order in which the initialization
forms are run for the slots defined by that class, and that the
order of the class precedence list determine the order for the entire
instance.
>In terms of the order of evaluation of the INITIALIZE-INSTANCE methods, it
>always seemed to me that method combination was how we should control
>that, but that the most sensible default order was most general to most
>specific (that is, like :AFTER).
In fact, the rules for method combination and initialization on
pg. 1-21:1-25 could determine this. I can't see any reason to
special case INITIALIZE-INSTANCE.
I'll postpone comments on the &REQUIRED-KEY proposal and Gregor's
proposal for a functional interface to initialization until I've
had a chance to study them.
jak
∂06-Jun-87 1636 RPG Order of Initialization
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Jak sez:
``This says nothing, however, about the order in which the initialization
forms for all the slots are run.''
I respond:
This say everything about how stupid I am when I read messages about CLOS.
The two choices must be some ordering depending on the textual order
within a DEFCLASS and on the CPL for inherited slots, or else it is
an error to depend on it.
-rpg-
∂08-Jun-87 1907 Bobrow.pa@Xerox.COM Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 8 Jun 87 19:07:03 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 08 JUN 87 18:38:46 PDT
Date: 8 Jun 87 18:38 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Open Issues in 87-002
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870608-183846-1250@Xerox>
I was reading over the spec the last few days, and have found the
following open issues that need to be resolved (or issues that I would
like to open). Comments please.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class? Gregor,
what is the answer in PCL right now?
p1-13 What is the initial class hierarchy in CLOS? I recall a message
by Sonya implying she was working on capturing our agreement at Ricky's.
Is there a rewritten section on this?
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
p1-24 Sshould we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
p1-20 Reference to type system correspondence to class system.
------
p2-3 Functions underlying the commonly used macros is neither complete
nor correct. The generic-functions add-method, get-method,
get-setf-generic-function, and remove-method should be in the
metaobjects chapter. make-method (p45)and make-generic-function (p42)
should be removed as soon as we have the initialization protocol set.
p2-6 I think we have reached agreement on the extension to
call-next-method to take arguments. Do I hear a volunteer to write up
this page.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Comments?
p2-16 We have agreed that we don't yet know whether the :constructor
option should be part of defclass.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here "returns the name of the class"
p2-22 Same comment as 2-19
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
p2-39 Arguments: "list of t's" should be replaced by "list of classes
named t" since get-method only takes specializers, not names of
specializers.
p2-40 Should be specified that get-setf-generic-function is set-able
(see 1-18
p2-44 INITIALIZATION PROTOCOL for make-instance.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
p2-51 print-object should take a depth argument.
p2-54 slot-missing should be documented
∂09-Jun-87 0719 skeene@STONY-BROOK.SCRC.Symbolics.COM Open Issues in 87-002
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 07:19:39 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168008; Tue 9-Jun-87 10:18:45 EDT
Date: Tue, 9 Jun 87 10:18 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Open Issues in 87-002
To: Bobrow.pa@Xerox.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870608-183846-1250@Xerox>
Message-ID: <870609101827.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Line-fold: No
Date: 8 Jun 87 18:38 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
I was reading over the spec the last few days, and have found the
following open issues that need to be resolved (or issues that I would
like to open). Comments please.
p1-13 What is the initial class hierarchy in CLOS? I recall a message
by Sonya implying she was working on capturing our agreement at Ricky's.
Is there a rewritten section on this?
It's almost done. I'll finish it up this week and send it to the list.
∂09-Jun-87 0803 kempf%hplabsc@hplabs.HP.COM I. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:03:35 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:03:22 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:02:18 pdt
Date: Tue, 9 Jun 87 08:02:18 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091502.AA00446@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: I. Formal Specification of Gen. Fcn. Invocation
For some time now, I have been somewhat bothered by the lack of
precision in the 87-002 specification of method invocation. While
the rest of the document (particularly the inheritance algorithm)
is fairly precisely worded, the section of Part 1 on method combination
and calculation of the effective method is fairly loose and informal.
Until recently, I've been involved in getting an attractively performing
prototype of CLOS up for our internal applications developers, and
so have not had any time to look at the issue in any detail. However,
having reached a checkpoint in that effort, I decided to revisit the
issue and attempt a formal specification of method invocation and
combination.
I will post the results in a series of three notes which deal with
the three aspects of calculating the effective method:
1) Determining the set of applicable methods,
2) Sorting the set of applicable methods by precedence order,
3) Calculating the effective method from the sorted set of
applicable methods.
I would hope that one of the committee members with interest and
inclination would check through the specification and offer any
corrections or additions, and that the 87-002 document could be
amended to include the result. If amending the document turns out
to be not possible, perhaps some other medium could be found for
presenting the result.
As an "executive summary", here is a short overview of the result:
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
requires that CALL-NEXT-METHOD in the least specific :AROUND method
behave fundamentally differently than in other instances. It also
contradicts the statement in the middle of the page that the
most specific :AROUND method provides the value for the invocation.
I suspect it is a typo, and would suggest that the statement in
the middle of the page prevail.
2) The case of having two EQL specializers on the same parameter
which differ during sorting of applicable methods cannot occur.
It is forbidden by the way in which the set of applicable methods
is constructed. An ambiguous statement in the second paragraph at
the top of pg. 1-22 implies that it can, however.
3) The least formal aspect of this specification is Part 3).
I think that some form of temporal logic would be needed to
do this correctly (I may be wrong, however), and so, rather
than go to that machinery, I simply made some general observations
and reasoned somewhat informally. Ultimately, it might be worth
doing the exercise.
Walter Olthoff, in our lab, has done some preliminary work to
cast the specification into the Axis executable formal specification
language, and we may continue this effort as an additional check
on accuracy.
I've also made some initial notes on an application of how this
specification could be used (for anyone who thinks its a waste
of time). In particular, it is possible to derive conditions on
the actual parameters which limit changes in the set of applicable
methods, changes in the sorted list of applicable methods, or both,
it arguments are allowed for CALL-NEXT-METHOD. These conditions
may be useful in construction compile time optimizations, for example.
Finally, the restriction to standard character sets has required
the use of bizarre (for formal methods) notation. For this, I
apologize. One of these days e-mail will support enough bandwith
that we can send around bitmaps.
jak
∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM II. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:03:59 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:03:55 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:02:47 pdt
Date: Tue, 9 Jun 87 08:02:47 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091502.AA00451@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: II. Formal Specification of Gen. Fcn. Invocation
Formation of the Set of Applicable Methods
Given, a generic function invocation:
(gf a(1) a(2) a(3) ... a(n) )
where:
gf = generic function name
a(j) = jth actual parameter
Let:
A = { a(j) }, j=1 ... n
M = { m(i) | m(i) is a method function for gf}
m = number of required parameters for gf
We seek to form the set of applicable methods, MA. The 87-002
wording about how this is done is rather vague:
Given a generic function and a set of arguments, the
applicable methods are all methods for that generic
function whose parameter specializers are satisfied
by their corresponding arguments.
A suggested rewording, which would tighten up the specification
is:
Given a generic function invocation, the applicable
methods are all methods all of whose formal parameter
specializers satisfy Relationship R with respect to
the corresponding actual parameters.
We now define Relationship R.
Let:
F(i)={ f(j) | f(j) is a formal parameter specializer for m(i) }
1 <= j <= m
Note that the F(i) are ordered sets, whose elements match one for one
with the elements of A. In cases where there are more required parameters
than specialized parameters, we extend F(i) using T as the specializer,
indicating that any actual parameter will match the formal parameter
specializer.
Define c(j) as the class of actual parameter a(j). With apologies
to Knuth, define Algorithm I as the algorithm used to calculate
the class precedence list for c(j), and cpl(j) as the result of
applying Algorithm I to c(j). Since the class precedence list is
a totally ordered set, we can define the index operator to return
the index of c(l) in the class precedence list:
index: class-object x cpl -> nat* (* is needed for error case)
This operation will be needed during sorting.
The following predicates map elements of f(j) into booleans:
eql-specializer-p = true if f(j) is a quoted object
false otherwise
class-specializer-p = true if f(j) is a class object
false otherwise
Relationship R is satisfied for one of the F(i) if and ony if, for
all (f(j), a(j) ), j = 1 ... n, either:
eql-specializer-p(f(j)) AND a(j) = f(j)
OR
class-specializer-p(f(j)) AND f(j) element cpl(j)
We denote the set of applicable methods as MA, and go on to
specifying the sorting algorithm.
jak
∂09-Jun-87 0804 kempf%hplabsc@hplabs.HP.COM III. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:04:29 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:04:28 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:03:24 pdt
Date: Tue, 9 Jun 87 08:03:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091503.AA00467@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: III. Formal Specification of Gen. Fcn. Invocation
Sorting the Set of Applicable Methods
Let:
MA = { ma(i) | ma(i) is an applicable method }
F(i) = { f(j) | f(j) is a formal parameter specializer for ma(i) }
Define the predicate
class-equal-p: class-object x class-object -> boolean
as:
class-equalp(f(l),f(m)) = true if f(l) and f(m) represent
the "same" class
false otherwise
We assume that the F(i) are totally ordered, with the ordering determined
by the :ARGUMENT-PRECEDENCE-ORDER for the generic function (default
being left to right).
Taking the F(i) pairwise, we define the equivalence relationship
"qualifier equal" (denoted =(q) ) on the corresponding ma(i)
as follows.
Let f(i,k) and f(j,k) be the kth elements from F(i) and F(j), respectively.
Then ma(i) =(q) ma(j) if and only if:
( eql-specializer-p(f(i,k)) AND eql-specializer-p(f(j,k))
AND f(i,k) = f(j,k)
)
OR
( class-specializer-p(f(i,k)) AND class-specializer-p(f(j,k))
AND class-equal-p(f(i,k),f(j,k))
)
for all (f(i,k),f(j,k)), k = 1 ... n
Note that =(q) groups the ma(i) into equivalence classes, with the
members of an equivalence class being distinguishable only by virtue
of their method qualifiers.
Let MAQ be the set of equivalence classes formed by applying =(q)
to MA. We impose a total ordering on MAQ by the following procedure.
For all maq(i), maq(j), i != j, select an ma(i) and ma(j) and
let F(i) and F(j) be the respective sets of ordered formal parameter
specializers.
Since ma(i) and ma(j) are from different equivalence classes,
there will a least k, 1 <= k <= n, for which the f(.,k) are
not equal, with the f(.,k) being ordered with respect to the ordering
imposed by the generic function.
For that k, let cpl(k) be the class precedence list for the
class c(k) of the matching formal parameter a(k). Define the
following predicate:
cpl-precedes-p: class-object x class-object x cpl -> boolean
as:
cpl-precedes-p(c(l),c(m),cpl) = true if index(c(l),cpl) <=
index(c(m),cpl)
false otherwise
We say that maq(i) is more specific than maq(j)
(written maq(i) <(p) maq(j) ) if and only if one of the following
is true:
1) eql-specializer-p(f(i,k))
2) class-specializer-p(f(i,k)) AND (NOT (eql-specializer-p(f(j,k)))
AND cpl-precedes-p(f(i,k),f(j,k),cpl(k))
Otherwise maq(j) <(p) maq(i).
Note that we need not even consider the case in which:
eql-specializer(f(i,k)) AND eql-specializer(f(j,k))
since construction of the set of applicable methods assures that
f(i,k) = f(j,k) if this true, in which case ma(i) and ma(j) would
be in the same equivalence class, or would not differ on specializer
k.
We denote the totally ordered set of qualifier equivalence classes
as MAQS and go on to specify the calculation of the effective
method.
jak
∂09-Jun-87 0805 kempf%hplabsc@hplabs.HP.COM IV. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:05:04 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:04:50 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:03:47 pdt
Date: Tue, 9 Jun 87 08:03:47 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091503.AA00472@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: IV. Formal Specification of Gen. Fcn. Invocation
Calculation of the Effective Method
Given the totally ordered set of method equivalence classes, MAQS,
the effective method (what actually gets executed) needs to be
formed.
In the general case, nothing can be said formally about how to
calculate the effective method, because the metaclass function
COMPUTE-EFFECTIVE-METHOD can return any Lisp form, if user
defined method combination is applicable.
We therefore restrict consideration to standard method combination.
We now need to break down the equivalence classes in MAQS and
sort out the methods based on their qualifiers.
From the sorting calculation, we remember that two applicable methods
are qualifier equivalent (written =(q)) if they are the same, except
for their method qualifiers. Applicable methods which are =(q) form
equivalence classes, which are sorted by precedence order, with
the precedence order being designated by <(p).
Define the following predicates:
primary-p: method -> boolean
primary-p(m) = true if m is an unqualified (primary) method
false otherwise
around-p: method -> boolean
around-p(m) = true if m is an :AROUND qualifed method
false otherwise
before-p: method -> boolean
before-p(m) = true if m is a :BEFORE qualified method
false otherwise
after-p: method -> boolean
after-p(m) = true if m is a :AFTER qualified method
false otherwise
Note that restriction to standard method combination means that
the following:
NOT (primary-p(ma(i)) OR around-p(ma(i)) OR before-p(ma(i))
OR after-p(ma(i))
)
cannot occur, for ma(i) element of MA, the set of applicable methods.
Given an ma(i), let the function:
preceedes-p: method x method x sorted-=(q)-set -> boolean
take two methods and the sorted set of =(q) equivalence classes
and return true if the equivalence class of the first argument is
more specific than that of the second.
Form the following four sets:
MR = { ma(i) | ma(i) element MA AND around-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MP = { ma(i) | ma(i) element MA AND primary-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MB = { ma(i) | ma(i) element MA AND before-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
MF = { ma(i) | ma(i) element MA AND after-p(ma(i)) AND
preceeds-p(ma(i),ma(j),MAQS) if i < j
}
Specification of standard method combination requires that the
execution sequence for the four sets be ordered as follows:
MR -> MB -> MP -> MF -> {mr(1) | mr(m), m = cardinality(MR) }
Complete execution of MB and MF is guaranteed, if either MR = {}
or mr(m) calls CALL-NEXT-METHOD, so transferring control to mb(1).
In general, unless the method body is coded otherwise, only mr(1)
need be completely executed. However, mp(1) must exist (even if
it is not executed) or an error occurs. (Aside: was this the
intended behavior? It seems to me that making control transfer
from the :AROUND method to the primary method dependent on
whether or not the user codes the least specific :AROUND method
with a CALL-NEXT-METHOD makes the :AROUND method more like a
primary, in the qualitative sense.)
The end sequence of effective method execution is ambiguously
specified. The middle of pg. 1-24 implies that, given MR exists,
then the return value is determined by mr(1), the most specific
:AROUND method, while the bottom of the page implies that,
given a sequence of execution transfers occurs in which execution
leaves MR through the least specific method (mr(m), m = cardinality(MR)),
then control transfers back to the calling continuation
for the entire generic function invocation, rather than
through return of the CALL-NEXT-METHODs to mr(1). I believe this is a typo.
As a solution, I would suggest that CALL-NEXT-METHOD in mr(m) behave
exactly the same as in other cases. The "next" method in this case
would be one of mb(1) (the first :BEFORE method) or mp(1) (the first
primary), depending on whether or not MB = {} (i.e., if there are
any :BEFORE methods). When CALL-NEXT-METHOD returns, control returns
to mr(m-1), and, eventually, to mr(1), which then controls the return
value.
In any event, control transfer from MR to MB can occur only via
a CALL-NEXT-METHOD in mr(m). Once control transfer to MB has occured,
MB is fully executed, then (at least) mp(1) and any other mp(j) via
CALL-NEXT-METHOD. After execution of the MP, MF is fully executed,
and control returns to mp(m). Depending on whether you believe
the middle or bottom of 1-24, mp(m) either returns the primary
value directly to the generic function calling continuation,
or the CALL-NEXT-METHOD in mp(m) returns the value
to its continuation, etc., until mp(1) is reached,
where the value is returned to the gf's continuation.
Additional rules on pg. 1-25 spell out where CALL-NEXT-METHOD can
be used, and the logic behind standard method combination.
jak
∂09-Jun-87 0854 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 08:54:10 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 08:53:45 pdt
Received: by hplabsc ; Tue, 9 Jun 87 08:52:15 pdt
Date: Tue, 9 Jun 87 08:52:15 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091552.AA01177@hplabsc>
To: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Subject: Re: Order of Initialization
>Jak sez:
>
>``This says nothing, however, about the order in which the initialization
>forms for all the slots are run.''
>
>I respond:
>
>This say everything about how stupid I am when I read messages about CLOS.
>
It's difficult to maintain continuity in a discussion when the lag in
a reply is a day. Not your fault.
>The two choices must be some ordering depending on the textual order
>within a DEFCLASS and on the CPL for inherited slots, or else it is
>an error to depend on it.
>
>
As I see it, Common Lisp does one of three things when the order of
evaluation matters:
1) Specifies the order, as is the case with the order of evaluation
of function arguments, or PROGN,
2) Gives the programmer a construct in which the order is specified
and one in which it is not, as in LET and LET*.
3) Does not specify in what order evaluation occurs. DEFSTRUCT is
in this category (except for the statement that initialization
forms are evaluated in the lexical context of the DEFSTRUCT
definition). This would leave it up to the implementation.
I think 1) should be the case. This avoids making it implementation
dependent (case 3) and avoids having to introduce extra syntatic
machinery (case 2).
jak
∂09-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 09:33:42 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 09:33:41 pdt
Received: by hplabsc ; Tue, 9 Jun 87 09:32:24 pdt
Date: Tue, 9 Jun 87 09:32:24 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091632.AA02166@hplabsc>
To: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Open Issues in 87-002
Some opinions on the open issues note which Danny posted.
>p1-12 Should defclass be allowed to change the metaclass of an existing
>class?
I think DEFCLASS shouldn't be allowed to change the metaclass, since
the representation for instances of classes with the two different
metaclasses might be radically different.
>p1-17 "It is currently under discussion whether to provide constructs
>for giving generic functions local names." Do we want to have this
>discussion, or to punt on this syntax. I recall we did come up with some
>reasonble semantics for a GFLET and GFLABELS.
There have been a couple times when I've thought this would be handy.
On the other hand, we may ultimately be accused of junking up the
standard with things that some people don't need. On the presumption
that someone will accuse us of that anyway, it would probably be a good idea
to look into this. I believe there was some discussion of a GLAMBDA
in addition? Perhaps this functionality could be achieved by providing
a GFUNCTION special form (like the FUNCTION special form), which takes
a list of lambda expressions and produces a generic function object.
I suppose we'll need a reader macro for this as well, like #'.
Arguments for these constructs are that it integrates generic functions
more smoothly into the language. Arguments against are that generic
functions are a higher level modularity mechanism than functions. My
opinion is that the former is probably more relevant, since the package
system is really the fundamental modularity mechanism for organizing
medium scale structure in Common Lisp.
>p1-18 It is not specified whether get-setf-generic-function is a
>setf-able form. I suggest that it be made so. This would allow one to
>trace setf-generic-function's without having to know their names.
I vote yes on this one. We are already having trouble tracing
SETF- generic functions, and need some kind of handle.
>p1-24 Sshould we have a call-next-method? which calls such a next method
>if it exists, else returns nil (rather than signalling an error?). This
>seems useful rather than having to define many base methods on object.
I think this would be a good idea, however, we need to consider the
performance tradeoff. If CALL-NEXT-METHOD is viewed as a means of
modifying the flow of control in the effective method, rather than
a fast way of invoking the next least specific method, I think this
would be useful (although a compiler would be free to optimize, if
it so chooses). In the most general case, the conditions determining
whether the set of applicable methods are still valid would need
to be re-checked on each invocation of CALL-NEXT-METHOD with parameters.
>p2-3 Functions underlying the commonly used macros is neither complete
>nor correct. The generic-functions add-method, get-method,
>get-setf-generic-function, and remove-method should be in the
>metaobjects chapter. make-method (p45)and make-generic-function (p42)
>should be removed as soon as we have the initialization protocol set.
Yes. Do people feel the initialization issues are well enough
understood that a proposed addition can be generated in Boston?
>p2-6 I think we have reached agreement on the extension to
>call-next-method to take arguments. Do I hear a volunteer to write up
>this page.
I'll do it, if nobody objects. I won't be able to do it by Boston,
however.
>2-13(?) The generic function class-name is not written up. It returns a
>name for the class as argument. I believe that (class-name class)
>should be setf-able. Can a class have more than one name? Should
>class-name then return a second argument -- the rest of the names this
>class is known by.
I think the class name should be changable, I don't think it should
have more than one name (at least, not for the default metaclass).
But I'm open to hearing some discussion on it, if anybody has any
ideas why it should be done.
>p2-19 Values: I thought we agreed that all top level forms should return
>the object. It says here "returns the name of the class"
This sounds like a typo. It should return the class object.
>p2-22 Same comment as 2-19
Ibid.
>p2-26 I believe that short form method combination ought to be a macro
>in the standard library, and documented there, not in the basic
>principles. I think the standard combinations :append, :and, :or, ...
>should also be put in the standard library too.
I agree.
>p2-35 The argument order of the setf method ought to be documented here.
>Gregor proposed that new-value be the first argument. Any problem with
>this?
I've gotten some complaints from my users that they would rather see
it as the second argument, and also the second argument to the
SETF- generic function. Personally, I don't particularly care, but
I thought I'd just pass this along.
>p2-44 INITIALIZATION PROTOCOL for make-instance.
Yes, this needs to be resolved.
>p2-51 print-object should take a depth argument.
Yes, this is needed. I think we need to maintain some compatibility
with DEFSTRUCT on this.
∂09-Jun-87 1008 kahn.pa@Xerox.COM Re: Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:08:17 PDT
Received: from Salvador.ms by ArpaGateway.ms ; 09 JUN 87 10:07:51 PDT
Date: Tue, 9 Jun 87 10:07:35 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
Subject: Re: Open Issues in 87-002
In-Reply-To: <870608-183846-1250@Xerox>
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870609-100751-1086@Xerox>
> p1-18 It is not specified whether get-setf-generic-function is a
setf-able
> form. I suggest that it be made so. This would allow one to trace
setf-generic-function's
> without having to know their names.
Maybe I'm confused, but how would it help tracing unless one re-compiled
all the setf's using the generic function? And how is the problem of
tracing setf's in CLOS any different than the general Common Lisp
problem?
References
Bobrow's message of Mon, 8 Jun 87 18:38:00 PDT -- Open Issues in 87-002
∂09-Jun-87 1035 Bobrow.pa@Xerox.COM Re: Open Issues in 87-002
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:35:13 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 10:33:13 PDT
Date: 9 Jun 87 10:33 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Open Issues in 87-002
In-reply-to: Ken Kahn <Kahn.pa>'s message of Tue, 9 Jun 87 10:07:35 PDT
To: Kahn.pa@Xerox.COM
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870609-103313-1143@Xerox>
>p1-18 It is not specified whether get-setf-generic-function
>is a setf-able form. I suggest that it be made so. This would
>allow one to trace setf-generic-function's without having to
>know their names.
Maybe I'm confused, but how would it help tracing unless one
re-compiled all the setf's using the generic function? And how is
the problem of tracing setf's in CLOS any different than the
general Common Lisp problem?
This is the same problem as tracing setf's of functions in CommonLisp.
But we have no two argument defsetf. Will someone who knows tell us how
that is done in some Common Lisps.
danny
∂09-Jun-87 1050 kempf%hplabsc@hplabs.HP.COM Re: Open Issues in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 10:48:58 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 10:48:36 pdt
Received: by hplabsc ; Tue, 9 Jun 87 10:47:25 pdt
Date: Tue, 9 Jun 87 10:47:25 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706091747.AA03141@hplabsc>
To: Bobrow.pa@Xerox.COM, Kahn.pa@Xerox.COM
Subject: Re: Open Issues in 87-002
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Here's how I do it:
(macroexpand '(setf <form> b))
then take whatever the name is from the macroexpansion. Turns out
that the names for things like SVREF are mostly well behaved
(LISP::SETF-SVREF) so I can guess most of the time in our Lisp.
This may be an issue for the cleanup committee (perhaps they are
already looking at it?).
jak
∂09-Jun-87 1104 Bobrow.pa@Xerox.COM Re: Order of Initialization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 11:03:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 10:55:03 PDT
Date: 9 Jun 87 10:54 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Order of Initialization
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue, 9
Jun 87 08:52:15 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Message-ID: <870609-105503-1199@Xerox>
jak says
As I see it, Common Lisp does one of three things when the
order of evaluation matters:
1) Specifies the order, as is the case with the order of
evaluation of function arguments, or PROGN,
2) Gives the programmer a construct in which the order is
specified and one in which it is not, as in LET and LET*.
3) Does not specify in what order evaluation occurs. DEFSTRUCT
is in this category (except for the statement that initialization
forms are evaluated in the lexical context of the DEFSTRUCT
definition). This would leave it up to the implementation.
I think 1) should be the case. This avoids making it
implementation dependent (case 3) and avoids having to introduce
extra syntatic machinery (case 2).
I think one should not depend on the order. Consider the ambiguity
resulting from two class definitions:
(defclass c1 ()
((x :initform (initx1))
(y :initform (inity))))
(declass c2 (c1)
((x :initform (initx2)))
These can be in a file in either order. Which order for eveluation of
(initx2) and (inity) do you think is correct. I can think of arguments
for both. Further, consider
(defclass c3 (c1)
((z :initform (initz))
(y :initform (inity2))
(x :initform (initx3))))
So my choice is 3, the user should not depend on the order.
danny
∂09-Jun-87 1136 Bobrow.pa@Xerox.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 11:36:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 11:35:01 PDT
Date: 9 Jun 87 11:34 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Tue, 9
Jun 87 08:02:18 pdt
To: kempf%hplabsc@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870609-113501-1274@Xerox>
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
requires that CALL-NEXT-METHOD in the least specific :AROUND method
behave fundamentally differently than in other instances. It also
contradicts the statement in the middle of the page that the most
specific :AROUND method provides the value for the invocation. I
suspect it is a typo, and would suggest that the statement in the
middle of the page prevail.
You must have a different reading of the words than I do. In the middle
of the page it says:
* If there are any :around methods, the most specific :around method is
called. It supplies the value for the method.
At the bottom it uses the phrase "If no :around methods were invoked"
This means that there are no :around methods. In this case, the value
is the value returned from what I will call the "effective primary
method" which will be the value returned by the most specific primary
method. The "effective primary method" is the method constructed
approximately as
(PROG2 (PROGN before1 .. beforen) primary1 (PROGN aftern ... after1))
where index 1 is more specific method than one with 2, ...
call-next-method always works on a list of effective methods, and always
calls the next in the list. The list for standard method combination is
(around1 ... aroundn effective-primary-method)
and hence there is no difference in what call-next-method does in the
two cases. The value is of course the value of the first method on this
list. I am not sure I understand your statement:
" the invocation of CALL-NEXT-METHOD in the least specific
:AROUND method would return the effective method invocation result
to the continuation (caller)"
Further in your formal description, you talk about control passing to
the before methods, without building a construct like
effective-primary-method. I think this is a mistake, since it loses the
nesting of the methods, and how values are returned.
-----
2) The case of having two EQL specializers on the same
parameter which differ during sorting of applicable methods cannot
occur.
I read the statement on page 1-22 as a proof of this statement.
∂09-Jun-87 1743 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Object creation discussion (at last!)
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 9 Jun 87 17:43:30 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ac03830; 9 Jun 87 20:24 EDT
Received: from ti-csl by RELAY.CS.NET id ag02593; 9 Jun 87 20:18 EDT
Received: by tilde id AA10877; Tue, 9 Jun 87 16:47:43 CDT
Message-Id: <2759261775-6137078@Jenner>
Date: Tue, 9 Jun 87 16:36:15 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Bobrow.pa@XEROX.COM
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Object creation discussion (at last!)
In-Reply-To: Msg of 2 Jun 87 18:37 PDT from Bobrow.pa@xerox.com
My message has two parts, the first one is about specifics and the
second one is about the general instance creation problem.
Part I:
I am trying to comment on the Gregor/Bobrow proposal as I see it after pasting
all the parts together:
from Bobrow:
(defmethod make-instance ((c standard-class) &rest initargs)
(let ((o (allocate-instance c)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o)
This is not enough, we need to be able to pass initargs to allocate-instance as
well.
Thus I think I would rewrite this (using Gregor's part):
(defmethod make-instance ((c standard-class) &rest initargs)
(let* ((init-args (merge-initargs initargs (default-initargs c)))
(o (apply #'allocate-instance c init-args)))
;o is an object with slots filled in by :initforms
(apply #'initialize-instance o (initial-args o initargs))
o))
Is this correct?
Now, who checks the legality of init-args? It seems it would be merge-initargs.
One thing I am not thrilled about with this proposal is that the legality check,
the defaulting and the merging of the initargs are done in three places. Here
is an example of what I don't like:
If a user wants to explicity override some initargs provided by a
superclass they can do that since everything is procedural and under
their control:
(defmethod class-legal-initargs ((class boat))
(let ((supers (call-next-method)))
(list* ':speed (remove :color supers))))
Now, if default-initargs is left to its usual form, it gets out of sync. We can
produce a default-init-args plist that would contain non legal initargs.
Part II:
Thinking about instance creation, it seems that we have a three
dimensional problem and we try to solve it using two dimensional
projections:
The first dimension is the class hierarchy.
The second is the initargs dimension.
the third is the operations dimension (legality check, defaulting,
side-effect).
Bobrow/Gregor tries to project the problem along the operation dimension,
thus losing the ability to do all the operations at the same place.
Dick tries to project the problem along the initargs dimension, losing
the ability to do legality check simply( which requires a global view
of the initargs).
The basic CLOS generic function mechanism is inherently two dimensional.
We have the class hierarchy dimension and the generic function dimension.
It seems normal that we run into problems if we try to use CLOS generic
function mechanism to model a three dimensional problem.
An ad-hoc solution like moon's can ignore such constraints and can do a
better job at preserving locality and modularity.
My opinion is that we should try to go back to an ad-hoc solution, maybe
as streamlined as it needs to make everybody comfortable with, instead
of trying to force fit instance creation into generic function calling
and adding few macros on top of it.
Patrick.
∂09-Jun-87 1819 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:18:47 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168871; Tue 9-Jun-87 21:16:13 EDT
Date: Tue, 9 Jun 87 21:16 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: SETF- method names
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706041702.AA04950@hplabsc>
Message-ID: <870609211606.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference.
The intent was that they would not have names at all, if I remember
correctly.
However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
You seem to be assuming that for any setf generic function, there will
be some symbol such that SYMBOL-FUNCTION of that symbol yields the setf
generic function. I don't see why. The Symbolics and TI
implementations, to take two examples, do not have any such symbols.
In addition, CLOS has some support for anonymous generic functions,
and presumably setf generic functions would be just one example of
such anonymous generic functions. I don't know how this was intended
to fit into TRACE and other debugging aids.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
If we're going to standardize on a way to name setf generic functions,
it should be a way to name methods as well. After all, you'd like to be
able to trace methods. I firmly believe that it should be based on the
"function spec" system used by Symbolics and TI, not on some scheme of
symbols with generated names. However in the past whenever I have
proposed "function specs" to the Common Lisp community, I got a lot of
abuse, so I'm tired of bothering.
∂09-Jun-87 1832 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:32:35 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168878; Tue 9-Jun-87 21:31:51 EDT
Date: Tue, 9 Jun 87 21:31 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 2 Jun 87 13:29 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870609213148.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Jun 87 1029 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I assumed that a generic function was a function and so could appear in
a function cell. Doesn't the Concepts chapter state that
(typep <generic function> 'function) => T
I presume that a generic function is a function under the cleaned-up
definition.
This is all true, but I think the actual issue was something else. It's
starting to come back to me: it's separating what the SYMBOL-FUNCTION
function does from what the implementation actually stores, so no one
can object on efficiency grounds. This is more of an implementation
note than a language specification.
Moon, do you know the date of your message discussing the non-keyword &key
arguments? What are the considerations?
I don't know the date, but the proposal name was KEYWORD-ARGUMENT-NAME-PACKAGE.
I'll send you the newest copy of it that I have, under separate cover (and
just to Dick).
∂09-Jun-87 1852 Moon@STONY-BROOK.SCRC.Symbolics.COM SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 18:52:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168882; Tue 9-Jun-87 21:52:18 EDT
Date: Tue, 9 Jun 87 21:52 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: SETF- method names
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706041702.AA04950@hplabsc>
Supersedes: <870609211606.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Comments: Added comment about tracing functions rather than tracing function-names.
Message-ID: <870609215209.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 4 Jun 87 10:02:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
The CLOS spec currently says nothing about what the names of the
SETF- generic functions will be, presumably because the intent
is to encourage use of generalized variable reference.
The intent was that they would not have names at all, if I remember
correctly.
However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
Places I could see it being introduced into the spec are:
1) As an additional keyword argument to DEFGENERIC-OPTIONS-SETF,
pg. 2-24:2-25. This could be used to specify the prefix for
generating the SETF- generic function name.
You seem to be assuming that for any setf generic function, there will
be some symbol such that SYMBOL-FUNCTION of that symbol yields the setf
generic function. I don't see why. The Symbolics and TI
implementations, to take two examples, do not have any such symbols.
In addition, CLOS has some support for anonymous generic functions,
and presumably setf generic functions would be just one example of
such anonymous generic functions. I don't know how this was intended
to fit into TRACE and other debugging aids.
CLtL's discussion of TRACE is very vague, so maybe the following doesn't
belong in the standard anyway. But is there any reason why TRACE
couldn't accept functions as arguments, rather than only accepting
function names? The main limitation seems to be that TRACE is a macro
and doesn't evaluate its subforms.
2) As an additional function, like GET-SETF-GENERIC-FUNCTION.
The implementation is simply:
(generic-function-name (get-setf-generic-function <name>))
but would not require the metaobject protocol function GENERIC-FUNCTION-NAME
be used.
If we're going to standardize on a way to name setf generic functions,
it should be a way to name methods as well. After all, you'd like to be
able to trace methods. I firmly believe that it should be based on the
"function spec" system used by Symbolics and TI, not on some scheme of
symbols with generated names. However in the past whenever I have
proposed "function specs" to the Common Lisp community, I got a lot of
abuse, so I'm tired of bothering.
∂09-Jun-87 1921 Moon@STONY-BROOK.SCRC.Symbolics.COM object / cleanup subcommittee interaction
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 19:21:37 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168903; Tue 9-Jun-87 22:21:01 EDT
Date: Tue, 9 Jun 87 22:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: object / cleanup subcommittee interaction
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870602003210.7.MOON@EUPHRATES.SCRC.Symbolics.COM>,
The message of 2 Jun 87 13:29 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>,
<870602-114805-4200@Xerox>,
<8706022335.AA00365@hplabsc>,
<870603-113213-2135@Xerox>,
<8706032153.AA14903@hplabsc>,
<870605-234940-2970@Xerox>
Message-ID: <870609222055.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Thanks for all the input. This is the summary I came up with:
This file is a list of things that the CLOS committee would like to see
cleaned up. I have tried to keep it brief. Where proposals have been
submitted to the Cleanup committee, the proposal name is listed as
"PROPOSAL: name". Where the Cleanup committee has assigned an issue
name, but there is no proposal yet, it is listed as "ISSUE: name".
1. PROPOSAL: FUNCTION-TYPE
Making FUNCTION be a genuine type (distinct from CONS).
2. PROPOSAL: KEYWORD-ARGUMENT-NAME-PACKAGE
Allowing keyword argument indicators to be non-keyword symbols.
3. ISSUE: DEFSTRUCT-CLOS
A recommendation to design a DEFRECORD facility to replace the part
of DEFSTRUCT that is not replaced by DEFCLASS.
4. ISSUE: PATHNAME-HASH-TABLE-TYPE-DISTINCT
Mandating a bunch of types (I don't have the complete list right now)
to be disjoint from a bunch of other types (again I don't have a
complete list right now) so that they can all be made into classes
without establishing any implementation-dependent subclass relationships.
5. PROPOSAL: SHARP-COMMA-SPECIAL-FORM
(in some Cleanup documents this is called LOAD-TIME-EVAL)
A macro should be able to include in its expansion the same sort
of thing that the #, reader-macro produces, enabling load-time
evaluation.
6. ISSUE: LEXICAL-ENVIRONMENT-ACCESSORS
Providing constructors and accessors for lexical environments.
This is somehow related to or a substitute for a symbol macro
facility [I don't understand the connection --Moon]
7. (no issue name)
Implementation note: clarify that the value returned by SYMBOL-FUNCTION,
and the value accepted by SETF of SYMBOL-FUNCTION, are not necessarily
what the implementation actually stores for purposes of function calling.
Specifically, (SETF (SYMBOL-FUNCTION x) gf), where gf is a generic function,
might create compiled code for method dispatching and store it in a place
associated with x, so that a call to x will compile as a call to that
compiled code, and will never touch the generic function object. However,
even if an implementation uses this technique, (SYMBOL-FUNCTION x) must
return the value gf, not the internal compiled code. Furthermore,
(FUNCALL gf ...) must produce the correct effect; it is permissible for
it to be slower than calling the internal compiled code.
8. (no issue name)
Require (deftype quote (object) `(member ,object)) to be built-in.
9. (no issue name)
Class objects must be acceptable to TYPEP and SUBTYPEP as type-specifiers.
This is probably part of CLOS rather than anything for the Cleanup committee.
∂09-Jun-87 2044 Moon@STONY-BROOK.SCRC.Symbolics.COM I. Formal Specification of Gen. Fcn. Invocation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Jun 87 20:44:17 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 168962; Tue 9-Jun-87 23:43:37 EDT
Date: Tue, 9 Jun 87 23:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: I. Formal Specification of Gen. Fcn. Invocation
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706091502.AA00446@hplabsc>
Message-ID: <870609234334.6.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 9 Jun 87 08:02:18 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
....I will post the results in a series of three notes which deal with
the three aspects of calculating the effective method....
I found that I was unable to comprehend any of this. I'll try again
some time when I have several hours available and no distractions.
I'm sure that the language in the document could be clearer and
less ambiguous, especially if it wasn't written by a committee, but
right now I'm not sure whether a more formal approach would make the
document easier to understand or would simply obfuscate it and end
up making errors more difficult to uncover.
1) Only one major inconsistency was found in the specification.
The requirement at the bottom of pg. 1-24 that the invocation of
CALL-NEXT-METHOD in the least specific :AROUND method would return
the effective method invocation result to the continuation (caller)
I am unable to find any such requirement. All I see is that the value
returned by the invocation of CALL-NEXT-METHOD in the least specific
:AROUND method is controlled by the most specific primary method.
Are you looking at an old version of the document perhaps?
2) The case of having two EQL specializers on the same parameter
which differ during sorting of applicable methods cannot occur.
It is forbidden by the way in which the set of applicable methods
is constructed. An ambiguous statement in the second paragraph at
the top of pg. 1-22 implies that it can, however.
This typo ("quoted" for "equal") was corrected in the corrections
handed out in March.
∂09-Jun-87 2234 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 22:34:10 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Tue, 9 Jun 87 22:32:55 pdt
Received: by hplabsc ; Tue, 9 Jun 87 22:31:45 pdt
Date: Tue, 9 Jun 87 22:31:45 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706100531.AA10636@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: SETF- method names
Cc: common-lisp-object-system@sail.stanford.edu
>If we're going to standardize on a way to name setf generic functions,
>it should be a way to name methods as well. After all, you'd like to be
>able to trace methods. I firmly believe that it should be based on the
>"function spec" system used by Symbolics and TI, not on some scheme of
>symbols with generated names. However in the past whenever I have
>proposed "function specs" to the Common Lisp community, I got a lot of
>abuse, so I'm tired of bothering.
>
Not being familiar with "function specs", I'm not in a position to
comment on them; however, I think the current situation is pretty
tenuous. As mentioned in the "Open Issues" note and subsequent
discussion, the way I usually trace SETF- functions is by macroexpanding
a form to see what the function name is. Admittedly, one could argue
this is an environmental thing, but since CLtL specifies the TRACE
function, there should be some means of doing this. Tracing methods
would also be nice. Maybe it would be best to defer this for the
moment, since it seems to be a more general problem of SETF-, and
can be solved in PCLOS/PCL (kludgily) by simply generating a more
tractable name, thus keeping my users happy.
jak
∂09-Jun-87 2349 Masinter.pa@Xerox.COM Re: object / cleanup subcommittee interaction
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jun 87 23:49:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUN 87 23:48:32 PDT
Date: 9 Jun 87 23:48 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: object / cleanup subcommittee interaction
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 9 Jun 87 22:20 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870609-234832-2213@Xerox>
I'll assign a random proposal name if you like:
8) ISSUE: TYPE-MEMBER-SINGLETON (issue is that (member t) is awkward
when there's only one)
Proposal TYPE-MEMBER-SINGLETON:QUOTE
As you say, point 7 (SYMBOL-FUNCTION may not be what's stored) is
really an implementation note rather than any language specification
change. I don't see that it requires a cleanup, for that reason.
I agree that your point 9 (TYPEP takes class object) really is more part
of the CLOS than a cleanup, (Without CLOS, there are no class objects,
and the issue is moot.)
∂10-Jun-87 0934 kempf%hplabsc@hplabs.HP.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Jun 87 09:33:46 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Wed, 10 Jun 87 09:32:47 pdt
Received: by hplabsc ; Wed, 10 Jun 87 09:31:14 pdt
Date: Wed, 10 Jun 87 09:31:14 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706101631.AA15389@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
Cc: kempf%hplabsc@hplabs.HP.COM
Comments from Dave Moon:
>I'm sure that the language in the document could be clearer and
>less ambiguous, especially if it wasn't written by a committee, but
>right now I'm not sure whether a more formal approach would make the
>document easier to understand or would simply obfuscate it and end
>up making errors more difficult to uncover.
Yes, a more formal approach may make the spec require more effort to follow.
What I hoped to avoid is a case like some Common Lisp implementations,
where an implementor picks up on one or two ambiguous phrases, interprets them
in a way which the majority of the implementers interpreted differently,
and thereby makes portablility of application code a lot harder to
achieve. Additionally, with a more formal approach, I think we may have
a better chance at convincing the ISO Committee at looking favorably
on CLOS semantics (even if they don't like the syntax), and perhaps the
Scheme community as well. As far as the object subcommittee's work goes, if
the consensus is that just now is not the time to introduce more
formalism, we can defer discussion until later. I'm planning on pursuing
the problem, since I think it is an interesting and important one, but
I'll avoid posting the details and only post questions or suggested
corrections, if people prefer.
>Are you looking at an old version of the document perhaps?
I have the version which was distributed at the March ANSI meeting,
along with the corrections distributed at the same meeting. If
the on-line version on SAIL or PARCVAX has corrections beyond
those, then I need to take a look at them. We have troubles
getting FTP connections here.
Danny Bobrow's comments:
> 2) The case of having two EQL specializers on the same
> parameter which differ during sorting of applicable methods cannot
> occur.
>I read the statement on page 1-22 as a proof of this statement.
The problem is the following. On page 1-21, last paragraph, there
is a description of the sorting process:
Compare the corresponding parameter specializers. When
a pair of parameter specializers are equal, proceed to
the next pair and compare them for equality. If all
corresponding parameter specializers are equal, the two
methods must have different qualifiers; in this case, either
method can be selected to precede the other (Comment:
this is also not strictly true, since they will actually
be in the same equivalence class. One could be a :BEFORE
and the other a :AFTER method, for example. In fact,
the two methods are incomparable with regard to precedence.)
If not all corresponding parameter specializers are equal,
the first pair of parameter specializers that are not
equal determines the precedence.
At this point, we move to pg. 1-22, and I'm assuming the rest
of the section deals with how to determine precedence. Determining
precedence for class specifiers is in the next paragraph, then the second last
paragraph in the section discusses EQL precedence:
If just one parameter is (QUOTE <object>), the method
with that parameter specializer preceeds the other
method. (Comment: Here comes the condition which cannot
occur.) If both parameter specializers are quoted
objects, the specializers must be quoted objects
(otherwise the two methods would not both have been
applicable for this argument).
In fact, at this point, it is not possible for both parameter
specializers to be quoted objects, because, if a specializer is
a quoted object, it must be EQL to the actual parameter for
the method, to even be an applicable method. If it is EQL to
the actual parameter, then two methods cannot differ on that
specializer, because all methods with an EQL specializer at
that parameter position will have the same specializer.
> 1) Only one major inconsistency was found in the specification.
> The requirement at the bottom of pg. 1-24 that the invocation of
> CALL-NEXT-METHOD in the least specific :AROUND method would return
> the effective method invocation result to the continuation (caller)
> requires that CALL-NEXT-METHOD in the least specific :AROUND method
> behave fundamentally differently than in other instances. It also
> contradicts the statement in the middle of the page that the most
> specific :AROUND method provides the value for the invocation. I
> suspect it is a typo, and would suggest that the statement in the
> middle of the page prevail.
>
>You must have a different reading of the words than I do. In the middle
>of the page it says:
>* If there are any :around methods, the most specific :around method is
>called. It supplies the value for the method.
>
>At the bottom it uses the phrase "If no :around methods were invoked"
>This means that there are no :around methods. In this case, the value
>is the value returned from what I will call the "effective primary
>method" which will be the value returned by the most specific primary
>method.
I'm not arguing with the case of no :AROUND methods, but rather
with the case of a CALL-NEXT-METHOD in the least specific :AROUND
method which causes control transfer to the effective primary
method. The statement in my copy of the spec says:
Otherwise, the value or values returned by the most
specific primary method are those returned by the invocation
of CALL-NEXT-METHOD in the least specific :AROUND
method.
My reading was that the following sequence of events occurs:
generic function invocation context:
most specific :AROUND
CALL-NEXT-METHOD -----------> to next most specific
next most specific :AROUND
CALL-NEXT-METHOD------------> to next next most specific
....
in least specific :AROUND:
CALL-NEXT-METHOD -------> transfer of control to
primary method
and execution of it.
Upon completion, transfer
back to least specific
THROW to generic <------- :AROUND method
function invocation
context.
In fact, on a closer reading (and looking at the following comments
about how to construct the effective primary method), I agree
that this interpretation is faulty.
> The "effective primary method" is the method constructed
>approximately as
>(PROG2 (PROGN before1 .. beforen) primary1 (PROGN aftern ... after1))
>where index 1 is more specific method than one with 2, ...
>
>call-next-method always works on a list of effective methods, and always
>calls the next in the list. The list for standard method combination is
>
>(around1 ... aroundn effective-primary-method)
>and hence there is no difference in what call-next-method does in the
>two cases. The value is of course the value of the first method on this
>list. I am not sure I understand your statement:
> " the invocation of CALL-NEXT-METHOD in the least specific
> :AROUND method would return the effective method invocation result
> to the continuation (caller)"
>
My initial reading of the bottom of 1-24 resulted in the interpretation of
the execution sequence as listed above. This is what I meant by
the statement.
>Further in your formal description, you talk about control passing to
>the before methods, without building a construct like
>effective-primary-method. I think this is a mistake, since it loses the
>nesting of the methods, and how values are returned.
I agree. I think the concept of the effective primary method is a
good one and it clarifies the concepts. Additionally, I think my
reading of the bottom of pg. 1-24 was confused by the fact that
I was interpreting the return value of the primary method with the
the return value of the generic function, since the first sentence
of the paragraph deals with the latter, and the second with the
former. It might be helpful to seperate out these two concepts,
in language something like:
The process of generic function invocation is completed
by returning value(s) to the invocation context. If
no :AROUND methods were invoked, then the most specific
primary method supplies the value(s) returned
by the generic function. If the most specific :AROUND
method was invoked, but control transfer to the
effective primary method via CALL-NEXT-METHOD in the
least specific :AROUND method does not occur, then
the return value(s) of the most specific :AROUND method
are the value(s) returned by the generic function. If
control transfer to the effective primary method does
occur, then the value(s) returned by the effective
primary method are potentially modifiable by the
:AROUND methods, and, again, the most specific :AROUND
method supplies the return value(s) for the generic
function invocation.
In the meantime, I'll look into incorporating the idea of an
effective primary method into the formalism.
jak
∂10-Jun-87 1006 RPG CLOS Document
To: common-lisp-object-system@SAIL.STANFORD.EDU
The version of the document on SAIL has the true errata corrected.
-rpg-
∂10-Jun-87 1114 skeene@STONY-BROOK.SCRC.Symbolics.COM Concepts chapter on standard type classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 11:14:14 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169429; Wed 10-Jun-87 14:13:43 EDT
Date: Wed, 10 Jun 87 14:13 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Concepts chapter on standard type classes
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610141334.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Below is a proposed section to go into the Concepts part of the document.
I'll also be sending a draft section to go into the Design Rationale
part of the document.
\beginSection{Integrating Types and Classes}
The \CLOS\ maps the Common Lisp type space into the space of classes.
Every class that has a name has a corresponding type with the same
name. {\bf defclass} and {\bf defstruct} define both types and classes.
The name of every class is a valid type specifier. In addition, every
class object is a valid type specifier. Thus the expression {\tt (typep
{\it object class\/})} evaluates to true if the class of {\it object\/}
is {\it class\/} itself or a subclass of {\it class}. The evaluation of
the expression {\tt (subtypep {\it class1 class2\/})} returns the
values {\bf t t} if {\it class1\/} is a subclass of {\it class2\/} or if they
are the same class; otherwise it returns the values {\bf nil t}.
Many but not all of the predefined Common Lisp type specifiers have a
corresponding class with the same name as the type. For
example, the type {\bf array} has a corresponding class named {\bf array}.
A class that corresponds to a predefined Common Lisp type is called a
{\bit standard type class\/}. Each standard type class has the class
{\bf standard-type-class} as a metaclass. It is not allowed to make an
instance of a standard type class with {\bf make-instance} nor to include
a standard type class as a superclass of a class.
The purpose for specifying that many of the standard Common Lisp types
have a corresponding class is to allow users to write methods that
discriminate on these types. The hierarchical relationships among
the Common Lisp types are maintained by the classes corresponding to
those types. Thus the existing type hierarchy is used for determining
the class precedence lists for each standard type class.
Method selection requires that a class precedence list can be
determined for each class, ordering the class and its superclasses from
most to least specific. In some cases, {\it Common Lisp: the
Language\/} does not specify a subtype/supertype relationship for two
supertypes of a given type. For example, {\bf null} is a subtype of
{\bf symbol} and {\bf list}, but {\it Common Lisp: the Language\/} does
not specify whether {\bf symbol} is more or less specific than {\bf
list}. The \CLOS\ specification defines those relationships for all
standard type classes.
The following table lists the set of standard type classes required by
\CLOS\. The superclasses of each standard type class are presented in
order from most specific to most general:
STANDARD TYPE CLASS SUPERCLASSES
array t
bit-vector vector, array, sequence, t
character t
complex number, t
cons sequence, t
float number, t
integer rational, number, t
list cons, sequence, t
null list, cons, symbol, sequence, t
number t
ratio rational, number, t
rational number, t
sequence t
string vector, array, sequence, t
symbol t
t
vector array, sequence, t
Note that instances of standard classes are type disjoint with all other
types.
Individual implementations can allow other type specifiers to have a
corresponding class. Also individual implementations can add additional
subclass relationships as long as they do not violate {\it Common Lisp:
the Language\/}.
Creating a type by means of {\bf defstruct} also creates a class in the
space of Common Lisp classes. Such a class is an instance of {\bf
structure-class} and a direct subclass of the class that corresponds to
the included structure, if any.
No type specifier that is a list, such as {\tt (vector double-float
100)}, has a corresponding class. No type defined by {\bf deftype} has
a corresponding class.
For a discussion on some of the design decisions underlying this aspect
of \CLOS\, see the section "Design Theories of the Integration of Types
and Classes".
\endSection%{Integrating Types and Classes}
∂10-Jun-87 1117 skeene@STONY-BROOK.SCRC.Symbolics.COM Design Rationale section on standard type classes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 11:17:11 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169433; Wed 10-Jun-87 14:16:24 EDT
Date: Wed, 10 Jun 87 14:16 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Design Rationale section on standard type classes
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610141615.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
\beginSection{Design Theories of the Integration of Types and Classes}
This section explains some of the design decisions regarding the
integration of the existing Common Lisp type system with the \CLOS\
class system. For background information, see the section
``Integrating Types and Classes''.
This section answers the following questions:
\beginlist
\item{\bull} Why do some of the standard Common Lisp types have a
corresponding class?
\item{\bull} Why don't all of the standard Common Lisp types have a
corresponding class?
\item{\bull} What were the guidelines for choosing which types would
have a class, and which would not?
\endlist
Question: Why do some of the standard Common Lisp types have a
corresponding class?
The purpose for specifying that many of the standard Common Lisp types
have a corresponding class is to allow users to write methods that
discriminate on these types; this is a powerful programming tool.
The standard type specifiers fit neatly into the method selection
model, but they are not suited to the complete \CLOS\ model, with respect
to building classes from superclasses, creating instances, and changing
the class of an instance. It is useful to discuss the practical and
conceptual distinctions between standard type classes and standard
classes. (A standard class is a user-defined class.) Standard type
classes have the following restrictions:
\beginlist
\item{\bull} A standard type class cannot be used as superclasses.
The difference between standard type classes and standard classes is
in the implementation of instances. Instances of a standard type class
are implemented in a specialized way that does not permit subclassing.
In some implementations some classes documented as standard type classes
might in fact be implemented as standard classes, but portable
programs cannot assume this.
\item{\bull} {\bf make-instance} cannot be used to create an instance
of a standard type class.
The capability of using {\bf make-instance} for standard type classes
gives no extra power or utility to the programmer. Also, the \CLOS\
model does not extend gracefully in this direction. Standard
classes have slots, but standard type classes have values of other
sorts (such as the value of an integer or the elements of an array)
which do not fit the {\bf make-instance} model.
\item{\bull} You cannot change the class of an instance of a standard
type class.
The semantics of changing an instance of a standard type class are not
at all clear. This is a basic difference between standard type
classes and standard classes.
\endlist
Question: Why don't all of the standard Common Lisp types have a
corresponding class?
It would be useful to extend the standard type classes to encompass the
full generality of Common Lisp type specifiers, but this raises
theoretical issues that are not yet appropriate for standardization.
These issues include:
\beginlist
\item{\bull} Deciding what to do when an argument is an instance of two
types, both of which have methods, but neither is a subtype of the
other. Some of the types in {\it Common Lisp: the Language\/}
have no constraints on their precedence relations to other types.
\item{\bull} The types that specify subranges present similar problems.
It is unclear how to determine the relative precedence of two
subranges of the same type.
\item{\bull} Dealing with Boolean combinations, such as negation, {\bf
and}, and {\bf or} presents problems with determinging relative
precedence order. For more information, see ``Boolean Classes'' by D.
McAllester and R. Zabih, a paper presented at the 1986 ACM First Annual
Conference on Object-Oriented Programming Systems, Languages, and
Applications.
\item{\bull} Some Common Lisp type specifiers are not defined clearly
enough in {\it Common Lisp: the Language\/} to be useful as classes.
Until the specification of these types is clarified, it would be
counterproductive to have corresponding classes for the types.
\item{\bull} Some types cannot be used for discrimination, such as {\bf
nil} and {\bf values}. No object can be an instance of these types
so there is no advantage to having classes for them.
\endlist
The \CLOS\ specification intentionally leaves room for adding more
standard type classes when these issues are resolved. For example,
when and if the Common Lisp Cleanup Committee provides a relative
precedence order on the types that currently lack them, these types
could have corresponding classes. Similarly, classes could be added
for the types whose specifications are currently too vague, whenever
the types are more rigorously defined.
Question: What were the guidelines for choosing which types would
have a class, and which would not?
The general guidelines were given above. The reasons for excluding
each individual type are given here:
{\it Boolean combinations and negation:\/}
{\bf and}
{\bf atom} - Negation {\bf (not cons}}.
{\bf or}
{\bf not}
{\it Subranges:\/}
{\bf bignum}
{\bf bit}
{\bf fixnum}
{\bf keyword}
{\bf member} - Subrange, if more than one argument is given.
{\bf mod} - Subrange of {\bf integer}.
{\bf satisfies} - Unclear subtype relations.
{\bf simple-array}
{\bf simple-bit-vector}
{\bf simple-string}
{\bf simple-vector}
{\bf standard-char}
{\bf string-char}
{\it The specification of these types is too vague:\/}
{\bf common}
{\bf stream}
{\bf function}
{\bf compiled-function}:
{\it No constraints on the precedence relations to other types:\/}
{\bf package}
{\bf readtable}
{\bf random-state}
{\bf hash-table}
{\bf pathname}
{\it No object can be an instance of this type:\/}
{\bf nil}
{\bf values}
{\it The meaning and existence of these types is
implementation-dependent:\/}
{\bf short-float}
{\bf long-float}
{\bf single-float}
{\bf double-float}
\endSection%{Design Theories of the Integration of Types and Classes}
∂10-Jun-87 1412 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: I. Formal Specification of Gen. Fcn. Invocation
Received: from [192.10.41.223] by SAIL.STANFORD.EDU with TCP; 10 Jun 87 14:12:08 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 136747; Wed 10-Jun-87 16:45:41 EDT
Date: Wed, 10 Jun 87 16:44 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: I. Formal Specification of Gen. Fcn. Invocation
To: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706101631.AA15389@hplabsc>
Message-ID: <870610164436.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 10 Jun 87 09:31:14 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>Are you looking at an old version of the document perhaps?
I have the version which was distributed at the March ANSI meeting,
along with the corrections distributed at the same meeting.
That's the same version that I have, so we're all right on that score.
∂10-Jun-87 1627 Bobrow.pa@Xerox.COM Re: SETF- method names
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Jun 87 16:27:36 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 JUN 87 16:04:43 PDT
Date: 10 Jun 87 16:04 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: SETF- method names
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 9 Jun 87 21:16 EDT
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870610-160443-1086@Xerox>
Kempf says: However,
since TRACE and other debugging aids require use of a function
name, lack of an easy handle for SETF- generic function names
(in the current implementation) requires that the user type in
a long, nonstandard name in order to get any debugging information.
Would it be appropriate to say anything about the SETF- generic
function name, realizing that nothing is said about such in CLtL?
There are two issues here.
1) SETF forms do not guarantee to call a function, and hence there is no
level of indirection one can count on to smash to build a tracing
facility.
2) With generic functions, there is such a level of indirection without
using a name, namely the generic function object. If TRACE were a
generic function that had an implementation dependent method on
GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
∂10-Jun-87 2132 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation Discussion
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 10 Jun 87 21:31:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 169962; Wed 10-Jun-87 23:34:53 EDT
Date: Wed, 10 Jun 87 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object Creation Discussion
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870610233442.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
In case you're wondering why you haven't heard from me recently: I'm carrying around
a 70-page sheaf of printout of the recent mail on the subject, which is gradually
getting notes written on it, but I haven't reached any conclusions worth repeating yet.
∂10-Jun-87 2338 RPG
To: common-lisp-object-system@SAIL.STANFORD.EDU
Ad Hoc Solutions
Patrick has provided a good analysis of the problems with initialization.
Let me add a little more to it and then let's think about how to proceed.
Initialization is an exemplar of a category of programs, some of which
will be things that users will want to write for themselves. For example,
suppose someone wants to write a DISPLAY-INSTANCE function that will take
a number of arguments; some of those arguments will be used to
supply information for the positioning of the displayed instance, others will
alter defaults that are normally supplied by the classes in the
class precedence list, where these defaults determine how the display will
look (icons, text, texture, background colors, feature colors, sound,
animation, etc). The end-user will want to customize the display by
defining methods on generic functions that get invoked by DISPLAY-INSTANCE.
In this example, we have the problem of determining the defaults as
contributed from the classes in the class precedence list, the problem
of checking the legality of the arguments, and the problem of distributing
the arguments to the right methods.
These are the same problems as in initialization, and the programmer will
need to define his own methodology for solving them if we use an ad hoc
approach for initialization. Assuming a declarative solution, I can even
imagine a programmer using the initialization mechanism to accomplish his
needs in the DISPLAY-INSTANCE problem.
My question is: Is this category of programs large enough that we need to
work Patrick's third dimension into CLOS? Or should we admit the weakness in
CLOS, because the category is too small or is not important? I don't know the
answer to this, and all I wanted to do was explore whether or not there was
a simple way to add the functionality to CLOS so that the decision is a
no-brainer.
-rpg-
∂11-Jun-87 0746 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 07:46:20 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 07:46:18 pdt
Received: by hplabsc ; Thu, 11 Jun 87 07:45:01 pdt
Date: Thu, 11 Jun 87 07:45:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111445.AA28326@hplabsc>
To: Bobrow.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Subject: Re: SETF- method names
>2) With generic functions, there is such a level of indirection without
>using a name, namely the generic function object. If TRACE were a
>generic function that had an implementation dependent method on
>GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
>
A this would solve the problem nicely, for those cases where the
funcallable object is well defined (fundefs, generic functions,
symbols w. function cell bound, methods, etc.).
The problem remains with SETF forms which take generalized variable
references, like SVREF, since there is currently no way to obtain
the funcallable object corresponding to the SETF "method" (to use
CLtL terminology).
jak
∂11-Jun-87 0819 kempf%hplabsc@hplabs.HP.COM Re: Order of Initialization
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 08:19:31 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 08:17:56 pdt
Received: by hplabsc ; Thu, 11 Jun 87 08:16:39 pdt
Date: Thu, 11 Jun 87 08:16:39 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111516.AA28670@hplabsc>
To: Bobrow.pa@Xerox.COM, kempf%hplabsc@hplabs.HP.COM
Subject: Re: Order of Initialization
Cc: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
>I think one should not depend on the order.
I agree, however, there may be cases where the order does matter.
>Consider the ambiguity
>resulting from two class definitions:
>
>(defclass c1 ()
> ((x :initform (initx1))
> (y :initform (inity))))
>
>(declass c2 (c1)
> ((x :initform (initx2)))
>
>These can be in a file in either order. Which order for eveluation of
>(initx2) and (inity) do you think is correct. I can think of arguments
>for both. Further, consider
>
>(defclass c3 (c1)
> ((z :initform (initz))
> (y :initform (inity2))
> (x :initform (initx3))))
>
In this particular example, the class precedence list for C1
would be:
(C1 STANDARD-OBJECT T)
the initializer for the X slot would be INITX2, and the initializer for
the Y slot would be INITY.
For C2, the class precedence list would be:
(C2 C1 STANDARD-OBJECT T)
and, according to the rules on pg. 1-8:1-9 of 87-002 (and
provided it is decided to stick with them), the initializer
for X would be INITX2 and that for Y would be INITY. If
one uses the class precedence list to impose a global ordering
on initialization, and the lexical order within the class
to impose a local ordering, one could argue that the initialization
order INITX2, INITY would make sense.
>So my choice is 3, the user should not depend on the order.
The kind of example I'm thinking about where the order of
initialization can matter is where some global information is
propagated from one initform to the other via a special, or
initialization of one slot requires previous slots to be initialized.
Like:
(defvar *screen-file-descriptor*)
(defclass window ()
(
(file-info (open-screen-file))
...
)
)
and initialization of the rest of the slots requires the special to
be bound.
I think that if the INITIALIZE-INSTANCE (or whatever is
ultimately agreed to be the name) user customizable method could be
designated the right place to put special initialization needs,
like the requirement for initialization to proceed in a particular
order, then the need for specifying the order within the class
itself goes away. However, it is important that the spec specifically
state that the user cannot depend on the order of initialization
for :INITFORMs, otherwise, someone is bound to do so.
jak
∂11-Jun-87 1120 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: SETF- method names
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Jun 87 11:03:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 170333; Thu 11-Jun-87 14:02:24 EDT
Date: Thu, 11 Jun 87 14:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: SETF- method names
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8706111445.AA28326@hplabsc>
Message-ID: <870611140213.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 11 Jun 87 07:45:01 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>2) With generic functions, there is such a level of indirection without
>using a name, namely the generic function object. If TRACE were a
>generic function that had an implementation dependent method on
>GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
>
Actually this opens its own can of worms. I can't figure out from CLtL
whether TRACE is intended to be an operation on function names, or on
functions. Perhaps it is intentionally left to the discretion of the
particular programming environment. All I know is that in Maclisp and
Zetalisp it was defined to be an operation on function names; but making
it operate on generic-function and method objects would make it an
operation on functions. Here's an example to show what I mean by the
distinction:
(defun foo (x) (print x))
(let ((f (function foo)))
(trace foo)
(funcall f 105))
If TRACE is an operation on function names, this just prints 105. If it's
an operation on functions, it generates tracing output as well.
A this would solve the problem nicely, for those cases where the
funcallable object is well defined (fundefs, generic functions,
symbols w. function cell bound, methods, etc.).
The problem remains with SETF forms which take generalized variable
references, like SVREF, since there is currently no way to obtain
the funcallable object corresponding to the SETF "method" (to use
CLtL terminology).
You actually mean the funcallable object called by the form that is
returned by the SETF "method"; those type of SETF-"methods" are macros,
unlike CLOS setf-methods, which are functions.
Yes, this is a problem and I don't know of any good answers to it; after
all, the SETF form might well expand into a call to a different function
depending on seemingly minor variations in details of the arguments.
Not a problem for CLOS, just a problem for CL. Your technique of
macroexpanding a sample form and assuming that the function that appears
there is the one that is going to be called is probably as good as any.
∂11-Jun-87 1243 kempf%hplabsc@hplabs.HP.COM Re: SETF- method names
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Jun 87 12:42:47 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 11 Jun 87 12:41:51 pdt
Received: by hplabsc ; Thu, 11 Jun 87 12:40:41 pdt
Date: Thu, 11 Jun 87 12:40:41 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8706111940.AA02450@hplabsc>
To: Moon@STONY-BROOK.SCRC.Symbolics.COM,
common-lisp-object-system@sail.stanford.edu
Subject: Re: SETF- method names
> Date: Thu, 11 Jun 87 07:45:01 pdt
> From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
>
> >2) With generic functions, there is such a level of indirection without
> >using a name, namely the generic function object. If TRACE were a
> >generic function that had an implementation dependent method on
> >GENERIC-FUNCTION, it would wqork fine. So again no names are needed.
> >
>
>Actually this opens its own can of worms. I can't figure out from CLtL
>whether TRACE is intended to be an operation on function names, or on
>functions. Perhaps it is intentionally left to the discretion of the
>particular programming environment. All I know is that in Maclisp and
>Zetalisp it was defined to be an operation on function names; but making
>it operate on generic-function and method objects would make it an
>operation on functions. Here's an example to show what I mean by the
>distinction:
>
>(defun foo (x) (print x))
>(let ((f (function foo)))
> (trace foo)
> (funcall f 105))
>
>If TRACE is an operation on function names, this just prints 105. If it's
>an operation on functions, it generates tracing output as well.
>
True, it could complicate implementations. The typical way of dealing
with tracing via names is to wrap the fundef with a wrapper function,
and hang the wrapper off the symbol's function cell. This doesn't demand
anything special of the fundef or symbol, since symbols are typically
writable. If TRACE becomes an operation on fundefs, it's got to modify
the fundef object, perhaps (extrapolating from the implementation
I'm aware of) putting a jump to the trace function as the first instruction
in the fundef. This may get difficult, if fundefs are in restricted
parts of memory, like nonwritable, which often is used for sharing
executable code between processes in different address spaces (again,
in the implementation I know best).
jak
∂12-Jun-87 1002 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Metaclass Protocol
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 12 Jun 87 10:02:05 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad01370; 12 Jun 87 12:54 EDT
Received: from ti-csl by RELAY.CS.NET id ag22147; 12 Jun 87 12:49 EDT
Received: by tilde id AA18373; Fri, 12 Jun 87 11:11:18 CDT
Message-Id: <2759501598-3981583@Jenner>
Date: Fri, 12 Jun 87 11:13:18 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Metaclass Protocol
This message is a first-cut attempt at a design rationale for the
metaclass protocol. The metaclass protocol being quite large, it will
be easier if we discuss and agree on the design rationale first.
We want to standardize the metaclass protocol to meet these objectives:
- Allow for portable compatible extensions to the CLOS model.
1)Some might change the instances representation/behavior while
retaining a compatible top-level interface; Persistent objects systems
and Distributed objects systems are some examples.
2)Some might extend the model by changing the classes behavior like
Delegation instead of Inheritance or they can implement another object
system for backward compatibility reasons (like Flavors, Common
Objects...). It would be desirable to allow a certain degree of
coexistence between classes belonging to different metaclasses.
- Allow for generic high level tools(Inspectors, generators, analyzers).
As a number of extensions will become available, there will be a need
for a single set of tools able to deal equally well with those
extensions.
Requirements:
The metaclass protocol should allow the implementation to pick the best
optimization strategy (in terms of code generation and instance
representation).
The metaclass protocol should allow for any programming development
styles. The idea is that an implementation should be able to support
both smooth incremental development and efficient wholesale file
compilation.
The metaclass protocol should support first class objects and anonymous
generic functions.
- Class behavior and instance behavior are othorgonal in CLOS. The
metaclass protocol must preserve this orthoganality. The metaclass
protocol should be as modular as possible. I would want to be able to
write a Persistent-mixin metaclass and then mix it with STANDARD-CLASS
to get a persistent standard-class or with FLAVORS to get a persistent
flavors metaclass, instead of having to implement a full-blown metaclass
for every case.
I think those objectives and requirements open up some specific issues:
- The side effects on CLOS objects (Classes, generic-functions, methods)
that spead across object links should be exposed.
Compute-class-precedence-list is a good example.
- It should be possible to access some exposed slots of a CLOS object
without side-effect. An inspector may need to access the
Class-precedence-list slot of a class without triggering
compute-class-precedence-list on the class. I think that means we need
to have a way to indicate when a slot contains valid data.
- We probably need to care about the compile environment. We don't have
to specify what it is but where, in our protocol it should be looked up
or side effected. At least we must make sure that we don't go against
the following statements:
1)Compile-file does not side effect the running environment.
2)It is possible to implement a cross loader (Something that loads files
in order to make some class definitions, etc that will affect
the compilation but not the running environment).
The list of requirement and issues is far from being complete, but it
probably covers enough to get the discussion started.
Patrick.
∂12-Jun-87 1204 Bobrow.pa@Xerox.COM Re: Order of Initialization
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 12 Jun 87 12:04:07 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 12 JUN 87 11:38:02 PDT
Date: 12 Jun 87 11:37 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Order of Initialization
In-reply-to: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>'s message of Thu,
11 Jun 87 08:16:39 pdt
To: Common-lisp-object-system@SAIL.STANFORD.EDU, RPG@SAIL.STANFORD.EDU
Message-ID: <870612-113802-1764@Xerox>
I think that if the INITIALIZE-INSTANCE (or whatever is
ultimately agreed to be the name) user customizable method could be
designated the right place to put special initialization needs,
like the requirement for initialization to proceed in a particular
order, then the need for specifying the order within the class
itself goes away. However, it is important that the spec
specifically state that the user cannot depend on the order of
initialization for :INITFORMs, otherwise, someone is bound to do so.
RIGHT (Meaning I agree)
∂15-Jun-87 1118 Gregor.pa@Xerox.COM new new initialization protocol blues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jun 87 11:17:55 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JUN 87 11:06:40 PDT
Date: 15 Jun 87 11:06 PDT
From: Gregor.pa@Xerox.COM
Subject: new new initialization protocol blues
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Bobrow.pa@Xerox.COM, Gregor.pa@Xerox.COM
Message-ID: <870615-110640-1411@Xerox>
Here is another example of a fully procedural initialization protocol.
This message also includes an example of using that protocol to solve
the x-y-rho-theta problem.
In this protocol, make-instance, compute-initargs,
class-default-initargs and class-legal-initargs are documented generic
functions.
The method for make-instance on standard-class is documented to call
compute-initargs and allocate-instance. The method for
allocate-instance on standard-class is documented to allocate storage
and evluate and store all the initforms. The method for
compute-initargs on object is documented to call class-default-initargs
and class-legal-initargs and do the kind of defaulting we have all come
to expect.
Many users will just want to define methods on class-default-initargs
and class-legal-initargs. Users trying to deal with problems like the
x-y-rho-theta problem will usually have to define methods on
compute-initargs as well.
(defmethod make-instance ((class symbol) &rest supplied-initargs)
(apply #'make-instance (class-named symbol) supplied-initargs))
(defmethod make-instance ((class standard-class) &rest
supplied-initargs)
(let* ((proto (class-prototype class))
(total-initargs (compute-initargs proto supplied-initargs))
(instance (apply #'allocate-instance class total-initargs)))
(apply #'initialize-instance instance total-initargs)
instance))
(defmethod compute-initargs ((object object) supplied-initargs)
(let* ((default (class-default-initargs object))
(legal (class-legal-initargs object))
(total supplied-initargs)
(magic-value (list nil)))
(do ((prop default (cddr prop))
(val (cdr default) (cddr val)))
((null prop))
(when (eq (getf total prop magic-value) magic-value)
(push (eval val) total)
(push prop total)))
(do ((prop total (cddr prop)))
((null prop))
(unless (member prop legal)
(error "~S is not a legal initarg for the class ~S"
prop
(class-of object))))
total))
(defgeneric-options class-legal-initargs (class)
(:method-comination-type append))
(defmethod class-legal-initargs ((class object)) '(:allow-other-keys))
(defgeneric-options class-default-initargs (class)
(:method-combination-type append))
(defmethod class-default-initargs ((class object)) ())
;;;
;;; Here is an example of all this in use to solve the notorious
;;; x-y-rho-theta problem.
;;; We define a class named position, which can be mixed into
;;; a class that implements either x-y-position primitives or
;;; rho-theta-position primitives. This class takes care of providing
;;; the other set of primitives, and more importantly takes care of
;;; handling the :x :y :rho :theta defaulting properly.
;;;
(defclass position () ())
(defmethod class-legal-initargs ((pos position))
'(:rho :theta :x :y))
(defmethod class-default-initargs ((pos position))
'((:x 0) (:y 0) (:rho 0) (:theta 0)))
(defmethod compute-initargs ((pos position) supplied)
(let ((x-p (memq ':x supplied))
(y-p (memq ':y supplied))
(r-p (memq ':rho supplied))
(t-p (memq ':theta supplied))
(defaults (class-default-initargs class)))
(when (and (or x-p y-p) (or r-p t-p))
(error "make up your mind loser"))
(cond ((and x-p y-p))
((and r-p t-p))
(x-p
(setf (getf supplied :y)
(eval-default-initarg (getf defaults :y))))
(y-p
(setf (getf supplied :x)
(eval-default-initarg (getf defaults :x))))
(r-p
(setf (getf supplied :theta)
(eval-default-initarg (getf defaults :theta))))
(t-p
(setf (getf supplied :rho)
(eval-default-initarg (getf defaults :rho)))))
(call-next-method pos supplied)))
(defmethod x-position ((p position))
(convert-rho-theta-to-x (rho-position p)
(theta-position p)))
(defmethod y-position ((p position))
(convert-rho-theta-to-y (rho-position p)
(theta-position p)))
(defmethod rho-position ((p position))
(convert-x-y-to-rho (x-position p)
(y-position p)))
(defmethod theta-position ((p position))
(convert-x-y-to-theta (x-position p)
(y-position p)))
(defclass x-y-position (position) (x y))
(defmethod initialize-instance :after
((pos x-y-position) &key x y &allow-other-keys)
(setf (slot-value pos 'x) x
(slot-value pos 'y) y))
(defclass rho-theta-position (position) (rho theta))
(defmethod initialize-instance :after
((pos rho-theta-position) &key rho theta &allow-other-keys)
(setf (slot-value pos 'rho) rho
(slot-value pos 'theta) theta))
∂15-Jun-87 1920 Bobrow.pa@Xerox.COM Re: new new initialization protocol blues
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Jun 87 19:20:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 JUN 87 15:06:21 PDT
Date: 15 Jun 87 15:06 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: new new initialization protocol blues
In-reply-to: Gregor.pa's message of 15 Jun 87 11:06 PDT
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@Sail.Stanford.edu, Bobrow.pa@Xerox.COM
Message-ID: <870615-150621-108@Xerox>
1) It is useful to be able to allocate storage for an instance without
having to evaluate all the initforms, for example, to build a
class-prototype without risking an error. Either this must be a
function that is called by allocate-instance, or it can be the job of
allocate instance. But in Gregor's message (and my earlier message) we
stated that
The method for allocate-instance on standard-class is
documented to allocate storage and evaluate and store all the
initforms.
A useful alternative may be to make the method for allocate-instance
only allocate storage for the instance. Then the primary method on
object for initialize-instance would be documented to evaluate and store
all the initforms.
2) Gregor's method not only exposes the proposed implementation of
initargs as methods, but suggests that the user must program using this
verbose style. Here is a useful macro, shown only in an example, that
would usually be used by users to specify how to handle inputs to
specify slot-values. The name of the macro can obviously be improved.
User-code:
(define-initialize-instance-after-method x-y-position (pos &key
start-the-engine)
((x :x number "a number") ;; initialize x a slot, checking its
type as a number
(y :second) ;; initialize y as a slot, using
keyword :second
z) ;; initialize z as a slot, using z as
the keyword
(when start-the-engine (fire-up pos))) ;; other user init code
----
Translation:
(defmethod initialize-instance :after
((pos x-y-position) &key start-the-engine
((:x #:g1) nil #:g2)
((:y #:g3) nil #:g4)
((z #:g5) nil #:g6)
&allow-other-keys)
(when #:g2
(check-type #:g1 number "a number")
(setf (slot-value pos 'x) #:g1))
(when #:g4
(setf (slot-value pos 'y) #:g3))
(when #:g6
(check-type #:g5 z-type) ;; this here if :type specified
in the class
(setf (slot-value pos 'z) #:g5))
;; Now comes the user-supplied body.
(when start-the-engine (fire-up pos)))
∂23-Jun-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM Object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 23 Jun 87 21:13:04 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 180419; Wed 24-Jun-87 00:12:34 EDT
Date: Wed, 24 Jun 87 00:12 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object creation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870624001226.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I've been studying the huge piles of mail on this subject. I'm not sure
that all of the ideas that were intended to be conveyed got through to
me, since there was so much mail and so many contradictions and minor
errors. Hence I apologize if what follows misses the point.
I couldn't find anything that directly addressed the issues I raised in
my message of 29 May; the one dividing things up into eight parts, of
which only three are actually needed if we want to keep things simple.
Did it get lost in the network?
My hardcopy of Dick's message of 31 May has "agreed" written all over
it. The conclusion I drew was that we aren't doing automatic
programming here and the generic-function-dispatch mechanism is pretty
limited in what programming tasks it can do automatically for us.
Still, it would be nice if we could come up with a general paradigm for the
procedural description of inheritance and use it uniformly for classes,
methods, slots, and initializations, and also make it available to users
with their own things-that-inherit; I don't have any specific
suggestions on this yet. One thing that I think we have learned is that
it seems to be a mistake to try to abstract away the caching that
happens in every real implementation of inheritance; we need to separate
the generic functions that gather and combine information from the
superclasses, from the generic functions that are called when an object
is created; the cache that sits between them needs to be made explicit.
I do have some thoughts to offer on the various schemes that have been
discussed for object creation at the meta-object level. It seems that
there are three rather different things that this could be for:
(1) The language used by ordinary, rank-and-file programmers to write
their programs.
(2) A procedural explanation of the semantics, so that there is no
magic and everything is explained in terms of something else. This
seems to be where Patrick's suggested generic, high-level tools fit in.
(3) A way to modify very basic aspects of the system's behavior,
for instance changing the way initargs inherit.
Taking these in order:
(1) I feel that a successful standard will provide simple ways to do
simple things. A good argument that controlling object creation only at
the meta-object level is too difficult is contained in Gregor's message
of 15 June. In the x-y-rho-theta example, the compute-initargs method
for position looks impressive, but if you study it carefully you will
realize that it is actually a complicated no-op! Regardless of whether
this method or the default method is called, the result will be the
same: a list containing the supplied initargs plus all of the
unsupplied ones with their default values from class-default-initargs.
I suspect that what happened here is that Gregor got so bogged down in
the complexity of describing the x/y/rho/theta class in these very
low-level procedural terms, that he forgot what the original point was.
Gregor is a smart guy, so I think what this shows is that an
object-oriented system that works this way is too difficult for anyone
to use without making mistakes.
Actually, this is probably a non-issue. Correct me if I am wrong, but
I think we have already agreed that we want a simple, high-level way to
do simple object-creation, with the procedural level behind the scenes
where it belongs.
(2) I think having a procedural explanation of the semantics is a good
idea. If I earlier gave the impression that I was opposed to that, it
was a misimpression. I do have some reservations, which I think fall
into two categories:
(a) This level of the standard involves a lot more detail than the
simple programmer interface, and there is correspondingly more
possibility for errors. Two examples that I noticed were failure to
carry along a lexical environment with forms, so that they can be
evaluated in the lexical environment in which they were written; and
confusion between method selection by the class of the instance versus
by the class of the class. These are small errors and fairly easy to
fix. For example, the first could be fixed by using functions instead
of forms and the second could be fixed by being consistent. The point
is simply that there are more things to go wrong and it will take longer
to get them right, because we are standardizing an implementation (at
some level of abstraction) rather than standardizing only a description
of how any implementation must behave.
(b) There is the danger of ripping too many holes in the veil of
abstraction between the user and the implementation, eliminating the
freedom to choose an implementation optimized for particular
circumstances. We have often made this mistake in the Lisp Machine
world in the past, and paid for it later. One example of this problem
is that I haven't been able to figure out whether some of the proposals
that have been discussed require the methods for class-default-initargs
to be called every time make-instance is called, thus ruling out
precomputation and caching of this information. Similarly I wasn't able
to figure out whether initializing many of the slots by copying a
template containing the values of constant initforms would be a valid
implementation, or whether the initforms actually have to be evaluated
at the time we say they are evaluated. A more serious problem is that
if the two operations, collection of the inherited default value forms
and evaluation of these forms, are combined into one generic function,
such as compute-initargs, it becomes impossible to collect these forms
without evaluating them and compile them into a function. This is
really the same point I made earlier, that trying to hide the existence
of caches isn't working. A third problem, which I mention because it's
of a completely different nature, is that if the standard mandates that
each little aspect of a class must be expressed as a method, and we
actually have to create method objects, compiled-function objects, and
generic-function dispatch table entries for each of those methods, it's
going to tie up a large amount of space. In a large system like Genera,
a rough, no doubt inaccurate estimate I made came out to 3/4 megabyte.
The point of these reservations is that if we're going to include this
level of detail in the standard, we have to be very careful what we say
and be sure we know what it implies.
(3) I'm not very happy about the idea of the user being able to redefine
very basic aspects of the behavior of the system, such as the way the
supplied initargs are combined with the default initargs. It seems like
this would weaken the idea of a standard, because there would be no
contract that the system could safely be assumed to obey. Actually what
bothers me here is not the idea that it is possible to redefine these
things, because I'm an open-system kind of guy and if people want to yank
the foundations out from under themselves that's okay with me. What really
bothers me is the idea that redefining this stuff will be part of ordinary
day to day programming, rather than just something that you do when you're
experimenting with new kinds of object systems; changing the rules should
be intentional, not accidental.
Where do we go from here? I think we should go back to figuring out
what the language used daily by rank-and-file programmers is. Once we
think we agree on that, we should verify that it makes sense by agreeing
on the procedural description of it; there will be some iteration of
these two steps (there has already been some). The biggest issue seems
to be what suite of features we want in that language, for example, is
the extra complexity of allowing initargs to be defaulted worthwhile?
∂24-Jun-87 1045 Moon@STONY-BROOK.SCRC.Symbolics.COM Object Creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jun 87 10:45:11 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 180885; Wed 24-Jun-87 12:59:08 EDT
Date: Wed, 24 Jun 87 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Object Creation
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870624125852.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Here's how I would do the x/y/rho/theta example:
;;; Abstract class that can be specialized to use either
;;; polar or cartesian representation
(defclass position () ())
(defmethod initialize-instance :before
((self position) &key x y rho theta)
(when (or x y)
(set-cartesian-position self (or x 0) (or y 0)))
(when (or rho theta)
(set-polar-position self (or rho 0) (or theta 0))))
;;; Default methods. One pair or the other must be shadowed.
(defmethod cartesian-position ((self position))
(multiple-value-call #'polar-to-cartesian (polar-position self)))
(defmethod set-cartesian-position ((self position) x y)
(multiple-value-call #'set-polar-position
self (cartesian-to-polar x y)))
(defmethod polar-position ((self position))
(multiple-value-call #'cartesian-to-polar (cartesian-position self)))
(defmethod set-polar-position ((self position) rho theta)
(multiple-value-call #'set-cartesian-position
self (polar-to-cartesian rho theta)))
;;; Internal subroutines for coordinate transformation
(defun polar-to-cartesian (rho theta)
(values (* rho (cos theta))
(* rho (sin theta))))
(defun cartesian-to-polar (x y)
(if (and (zerop x) (zerop y))
(values 0 0)
(values (sqrt (+ (* x x) (* y y)))
(atan y x))))
;;; Useful macro
(defmacro with-direct-slots ((instance) &body body)
`(with-slots ((,instance :use-accessors nil))
,@body))
;;; Instantiable class that uses cartesian representation
(defclass cartesian-position (position) (x y))
(defmethod cartesian-position ((self cartesian-position))
(with-direct-slots (self)
(values x y)))
(defmethod set-cartesian-position ((self cartesian-position)
new-x new-y)
(with-direct-slots (self)
(setq x new-x y new-y)))
;;; Instantiable class that uses polar representation
(defclass polar-position (position) (rho theta))
(defmethod polar-position ((self polar-position))
(with-direct-slots (self)
(values rho theta)))
(defmethod set-polar-position ((self polar-position)
new-rho new-theta)
(with-direct-slots (self)
(setq rho new-rho theta new-theta)))
∂24-Jun-87 1155 RPG Request to Moon for Thursday's Discussion
To: common-lisp-object-system@SAIL.STANFORD.EDU
Dave, could you possibly gather some information about the
current uses of initialization in Genera? It would be useful to
know what the most complex requirements are, what the typical
requirements are, etc, in a real system. For example, how often would
the CLOS :initform protocol serve?
-rpg-
∂25-Jun-87 0901 RPG Random Thoughts Concerning Initialization
To: common-lisp-object-system@SAIL.STANFORD.EDU
Reading over Gregor's latest proposal I am struck by the choices
we have:
1. In Moon's proposal, we introduce a new programming language within
the DEFCLASS syntax. This language solves the initialization problem
efficiently with minimal syntax. Other problems reducable to initialization
might also be so reduced by users, leading to confusing programming
methodologies.
2. In Gabriel's proposal, we introduce some additional lambda-list syntax
and semantics to effect the distribution of arguments to methods. This
also requires complex initialization protocol to be written in a verbose
manner, and it complicates lambda-lists in an unpleasant manner.
3. In Gregor's proposal, we solve the initialization problem by reducing
it to a problem of manipulating argument lists. The code (sans macros) is
verbose and complicated. In addition, we end up treating passed arguments
as lists, which I find to be an unpleasant exposure of representation.
If we approach the initialization question along the lines Gregor
suggests, and if we look at the nature of generic functions (dispatching
to code based on examination of passed arguments), it seems there is some
tendency towards introducing into the language a means of operating on
passed arguments. One reason we had trouble with generic functions that
discriminated on more than the required arguments is that we had a hard
time manipulating the passed arguments.
If we choose a solution to initialization that involves manipulating
passed arguments, we possibly ought to provide an abstraction for passed
arguments - a set of passed arguments along with a set of operators that
take them apart, put them together, and invoke functions on them? I
believe Seus [Talcott] went some distance in this direction.
∂02-Jul-87 0911 kempf%hplabsc@hplabs.HP.COM ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 2 Jul 87 09:11:09 PDT
Received: from hplabsc by hplabs.HP.COM with TCP ; Thu, 2 Jul 87 09:10:20 pdt
Received: by hplabsc ; Thu, 2 Jul 87 08:35:59 pdt
Date: Thu, 2 Jul 87 08:35:59 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
Message-Id: <8707021535.AA22501@hplabsc>
To: common-lisp-object-system@sail.stanford.edu
Subject: ECOOP Reaction to CLOS
My impression from talking to people at ECOOP was that most people
were fairly positive about Dick's talk.
He did get some flak about the inheritance algorithm, but I think this
was due to the presentation. If you tell someone that something is
too complicated to understand, the likely response is that you should
make the design simpler so they can understand it. In my opinion, it
is simply unacceptable to go around saying this. The algorithm isn't
any more complicated than the one used for LR parser generation
(to which Aho, Sethi, and Ullman devote 37 pages in the new Dragon
book) or normalization of a relational database schema (to which
Date devotes 23 pages).
The fact that the algorithm is the right one is bostered by a paper
by Ducournau and Habib at ECOOP, which examined a class of graph
linerization algorithms having desirable qualitative properties,
of which the CLOS algorithm is a member.
Therefore, I hope someone can stand up at OOPSLA and do a better
job of explaining it. It may take some time, and will probably
require some more examples, particularly of how things can go
wrong, but I think it will, in the end, gain more support for
CLOS and increase programmer understanding. People should feel
good about using it, not just because its the standard, but also
because it does what they want and they understand that.
I hope someone will post the results of the Boston meeting, particularly
any decisions on initialization.
Jim Kempf kempf@hplabs.hp.com
∂03-Jul-87 0843 Moon@STONY-BROOK.SCRC.Symbolics.COM ECOOP Reaction to CLOS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Jul 87 08:43:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 187240; Thu 2-Jul-87 16:58:59 EDT
Date: Thu, 2 Jul 87 16:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: ECOOP Reaction to CLOS
To: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8707021535.AA22501@hplabsc>
Message-ID: <870702165857.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 2 Jul 87 08:35:59 pdt
From: Jim Kempf <kempf%hplabsc@hplabs.HP.COM>
I hope someone will post the results of the Boston meeting, particularly
any decisions on initialization.
Definitely. Because of the long weekend, and because Gregor will be off
work Monday and Tuesday, you can expect to see this around the second half
of next week. I wouldn't say we made any hard and fast decisions, but we
certainly made a lot of progress and we should be able to finish that up
and make actual decisions through the mail. We talked about having another
meeting and the scheduling for that will have to be discussed through the
mail.
∂06-Jul-87 1130 RPG ECOOP Reaction
To: common-lisp-object-system@SAIL.STANFORD.EDU
As Kempf points out, there was some negative reaction to CLOS at my
presentation, but most of it was directed at the lack of encapsulation and
protection, multiple inheritance, and the use of CLOS as a knowledge
representation system. I might point out that most of the people who
raised objections during the presentation came up to me afterwards to get
a hold of the spec, the code, etc.
I want to make clear what it is I said about the CPL computation: I stated
that the effect of the CPL algorithm was difficult to understand, not that
the algorithm is difficult to understand. The difference between the two
is that an algorithm can be easy to grasp while a characterization of it
suitable for a programmer to understand is not available. In contrast,
the algorithm for computing the strongly connected components of a graph
is easy to understand as an algorithm, and it is easy to understand what
it does because the definition of a strongly connected component is easy
to understand. The CPL is understood to be a total ordering on a class
and its superclasses, but the only characteriztion of it that I know of is
that the CPL is the total ordering computed by the algorithm. That
algorithm is understandable at the operational level, but there is no easy
characterization of it.
What would constitute an understandable characterization of the CPL?
Here are some examples of approaches:
1. We could have a set of constraints on the classes such that the CPL
is the unique total ordering satisfying those constraints.
2. We could have a set of inheritance situations such that when two
graphs of classes were inherited in particular ways, the new CPL was
predictable. For example, suppose we have 2 graphs, G1 and G2, with no common
classes except for the class named T and suppose that C1 and C2 are the
bottom-most classes of G1 and G2, respectively; then if a class C is
a subclass of C1 and C2 in that order, the classes in G1 precede the classes
in G2, and the classes in G1 are in the same order as they are in the CPL
for C1 and similarly for G2; T comes last.
But we do not have such a characterization; Moon's constraints are close
to it, but not good enough. Possibly we can search for the
characterization. Remember that at the Palo Alto meeting in March, smart
people like Scherlis could not understand the effect of the algorithm,
although they (and he) thought the algorithm was simple.
Intellectual honesty compels me to point out things like this when
I address an audience. I suppose it annoys people when I do that,
but maybe we should give some thought to designing a language such that
there are few oppurtunities for ``Gabriel's inevitable critique.''
-rpg-
∂08-Jul-87 0928 RPG First Try at Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
At the Symbolics meeting we decided to introduce some terminology
about erroneous situations for use in the final document. Here is
a first attempt at that terminology - Sit is a situation and Syn is
syntax:
The terminology defined in 1 - 4 refers to situations that might occur,
while the terminology defined in 5 refers to syntax.
A ``situation'' is one of the following:
1. an expression in which the first form is given or specified and
the remaining subexpressions are either given, specified, or
evaluate to objects satisfying certain constraints;
2. a state of affairs within a running CLOS system.
Examples: When the function + is given a non-number as an argument, that
is a situation under definition 1; when a numeric operation causes an
arithmetic overflow, that is a situation under definition 2.
``Syntax'' refers to the nature of the lambda-list of a function,
the nature of the defmacro lambda-list of a macro, and the number and
nature of the subexpressions in a special form.
In the specification of CLOS, the behavior of programs in all situations
is described, and the options available to the implementor are defined; no
implementation is allowed to extend the syntax or semantics of CLOS except
as explicitly defined in the CLOS specification. In particular, no
implementation is allowed to extend the syntax of CLOS in such a way that
ambiguity between the specified syntax of CLOS and those extensions is
possible.
The following are descriptive phrases and their meanings:
1. ``When Sit occurs an error is signaled.''
The meaning of this terminology is:
a. If this situation occurs, an error will be signaled in code
compiled under all compiler safety optimization levels and in
the interpreter.
b. Valid CLOS programs may rely on the fact that an error will be
signaled in code compiled under all compiler safety
optimization levels and in the interpreter.
c. Every CLOS implementation is required to detect such an error
in code compiled under all compiler safety optimization levels
and in the interpreter.
2. ``When Sit occurs an error should be signaled.''
The meaning of this terminology is:
a. If this situation occurs, an error will be signaled at least in
code compiled under one compiler safety optimization level and
in the interpreter.
b. Valid CLOS programs may not rely on the fact that an error will be
signaled.
c. Every CLOS implementation is required to detect such an error
at least in code compiled under one compiler safety
optimization level and in the interpreter.
d. When an error is not signaled, the results are undefined (see
below).
3. ``When Sit occurs the results are undefined.''
The meaning of this terminology is:
a. If this situation occurs, the results are unpredictable. The
results may range from harmless to fatal to the running CLOS
system.
b. No valid CLOS programs should cause this situation to happen.
c. CLOS implementations are allowed to detect this situation and
signal an error, but no CLOS implementation is required to
detect the situation.
d. No implementation is allowed to extend the semantics of CLOS to
this situation; the effects of the situation may be harmless,
but they must remain undefined.
4. ``CLOS may be extended to cover Sit.''
The meaning of this terminology is that an implementation is free to treat
Sit in one of four ways:
a. When Sit occurs, an error is signaled;
b. When Sit occurs, an error is signaled at least in code compiled
under one compiler safety optimization level and in the
interpreter.
c. When Sit occurs, the results are undefined; or
d. When Sit occurs, the results are defined and specified.
In addition, this terminology means that:
e. No portable CLOS program can depend on the effects of this
situation, and all portable CLOS programs are required to treat
the situation as undefined.
5. ``Implementations are free to extend the syntax Syn.''
The meaning of this terminology is:
a. Implementations are allowed to define unambiguous extensions to
that syntax.
The CLOS specification may disallow certain extensions while allowing others.
*****************************************************************************
The following is a discussion of the motivation behind these terms. Of course,
there is no commitment yet to these terms: This is simply the first proposal.
The definition of a situation is designed to cover function invocations,
macro calls, and instances of the use of special forms as well as
conditions that might arise within a running CLOS system. A situation is
not a purely syntactic state of affairs, because the preconditions for an
error usually requires that something about the nature of the arguments
to a function, for example, be known. The wording of these definitions will
need further work.
On syntax, I believe we want the default to be that no extensions are
allowed - that is, any extensions must be explicitly allowed. I
particularly wish to disallow syntactic extensions that extend the number
of arguments to a function or a macro or the number of subexpressions in a
special form.
These terms are a reaction to current CLtL terminology and the various
interpretations of it. The entire gamut of interpretations of CLtL terms
is valid, but there are more interpretations than terms. This proposal is
intended to identify the reasonable interpretations of CLtL terminology
and provide terms for those intepretations, so that, I hope, the terms and
interpretations are one-to-one.
1. ``When Sit occurs an error is signaled.''
This term is borrowed from CLtL. I think we need a more precise definition
that talks about errors being signaled in code compiled under all compiler
optimization levels. Current practice in Common Lisp includes only
signaling errors in code that was compiled under high compiler safety
optimization levels. Because there is a constant desire to elide such
checks in compiled code on stock hadware, we should separate out cases in
which we want errors signaled in code compiled under all compiler
optimization levels from those in which we allow implementations to
provide a high-speed, unsafe operations - my recollection is that CLtL
``is an error'' was intended to accomplish that separation, but that is
not the current prevailing interpretation. Hence the term:
2. ``When Sit occurs an error should be signaled.''
Some people who interpret CLtL maintain that, under a strict reading of
CLtL, CLOS ``signals an error'' corresponds to CLtL ``signals an error''
and CLOS ``an error should be signaled'' corresponds to CLtL ``is an
error.'' This does not correspond to current practice, in which CLtL
``signals an error'' generally corresponds to CLOS ``signals an error''
or ``should signal an error,'' while CLtL ``is an error'' generally
corresponds to CLOS ``is undefined'' or ``is extendable.''
3. ``When Sit occurs the results are undefined.''
The intention of this is to allow implementations to not worry about what
happens in Sit, because CLOS does not permit programs to be written that
fall into Sit, and no implementation is allowed to extend the semantics of
CLOS to provide useful behavior in Sit. Some people have claimed that CLtL
``is an error'' corresponds to CLOS ``is undefined.''
I might expect that we would add wording to this to the effect that an
implementation may include documentation about a situation of this sort
that states that the results are harmless, but no implementation is
allowed to state what actually happens.
4. ``CLOS may be extended to cover Sit.''
This term in intended to cover yet another reading of CLtL ``is an
error,'' namely that an implementation is allowed to extend the language
to cover an otherwise erroneous situation.
5. ``Implementations are free to extend the syntax Syn.''
I believe we wish to control where extensions to CLOS are allowed to occur.
The first four terms are designed to control semantic extensions while the
fifth is designed to control syntactic extensions, which are somewhat
different.
I believe we want to define precise terms such as these and use them
exactly in the CLOS specification so that, rather than the CLOS
specification being a pseudo-user's-guide as CLtL is, it can be a
specification suitable for an implementor.
-rpg-
∂08-Jul-87 0938 RPG Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
One minor point that came up at the Symbolics meeting last Thursday
was category errors and whether we should try to outlaw them somehow.
Here is an example of a category error:
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
(make-instance (class-prototype (class-named 'apple-pie)) ...)
Here someone would be making a category error by defining a method on
MAKE-INSTANCE at the wrong level - the class level. What makes this easy
for a programmer to do this is the availability of CLASS-PROTOTYPE.
However, it is never hard to do because the programmer can write:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
to get his class prototype.
We have two alternatives:
1. Let sea of classes/metaclasses remain a miasma and inform
programmer that he ought not mix things up.
2. Define a notion of class category or classs level and have a
category of generic function for each class category.
-rpg-
∂08-Jul-87 1643 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 8 Jul 87 16:43:20 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa01894; 8 Jul 87 19:38 EDT
Received: from ti-csl by RELAY.CS.NET id aa05802; 8 Jul 87 19:31 EDT
Received: from Jenner by tilde id AA05525; Wed, 8 Jul 87 16:05:23 CDT
Message-Id: <2761765326-16486571@Jenner>
Date: Wed, 8 Jul 87 16:02:06 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Class redefinition and class-changed.
Redefining a class will provoke instances of this class to be changed to the new
class using the change-class protocol. However there is no specified way to
take advantage of the class-changed generic function.
Goals:
- There should be a way to define a method for class-changed on the obsolete
class and the class.
- This method needs to be defined before any the instances is changed,
otherwise it wouldn't get invoked on all the instances of the class.
Proposal:
Before committing the class to redefinition, we specify a way to get the
obsolete class objects and thus, define methods for class-changed. Since a
class redefinition will propagate down, it will be useful to get the closure of
all the redefintions.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION will return an alist whose keys are the
classes implicated in the class-redefinition of CLASS and whose contents are the
obsolete classes.
Syntax:
GET-OBSOLETE-CLASSES-FOR-REDEFINITION CLASS &optional (REDEFINITION-CLOSURE-P t)
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is a generic function.
CLASS is a class object
if REDEFINITION-CLOSURE-P not provided or non nil, all the classes implicated in
the class redefinition of CLASS are returned as keys of the resulting alist. If
REDEFINITION-CLOSURE-P is nil, then the alist returned contains only one entry
for CLASS.
Besides obsolete class creation, get-obsolete-classes-for-redefinition does not
side effect. In other words, it it OK to call it more than once and the returned
obsolete classes are EQ from one call to the other.
Once the methods are defined, the class redefinition can be executed.
Patrick.
∂09-Jul-87 1207 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 12:07:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUL 87 11:54:12 PDT
Date: 9 Jul 87 11:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Wed, 8 Jul 87 16:02:06 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870709-115412-4166@Xerox>
Goals:
- There should be a way to define a method for class-changed
on the obsolete class and the class.
- This method needs to be defined before any the instances is
changed, otherwise it wouldn't get invoked on all the instances of
the class.
Agreed.
The necessary and sufficient condition for this is to be able to get
hold of an obsolete version of a class.
Proposal:
Changing a class updates a database to allow the following generic
functions to work.
GET-OBSOLETE-VERSION class
returns the preceding obsolete version of this class, or NIL if none.
This allows users to define methods at any time on the obsolete class.
Obsolete classes themselves may also have an obsolete-version. Obsolete
classes also respond to
GET-UPDATED-VERSION obsolete-class
with the next class or NIL
This allows following the chain in the opposite direction
Providing this chain allows defining pair-wise updaters from an obsolete
to its updated version, a general updating protocal that will follow the
chain from any old version to the current version, and accelerators
between any old-version and any later version on the chain.
∂09-Jul-87 1326 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:26:09 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:24:30 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:23:58 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:24:38 pdt
Date: Thu, 9 Jul 87 13:24:38 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092024.AA22131@hplabsz.hpl.hp.com>
To: rpg@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
Cc: common-lisp-object-system@sail.stanford.edu
>I want to make clear what it is I said about the CPL computation: I stated
>that the effect of the CPL algorithm was difficult to understand, not that
>the algorithm is difficult to understand. The difference between the two
>is that an algorithm can be easy to grasp while a characterization of it
>suitable for a programmer to understand is not available. In contrast,
>the algorithm for computing the strongly connected components of a graph
>is easy to understand as an algorithm, and it is easy to understand what
>it does because the definition of a strongly connected component is easy
>to understand. The CPL is understood to be a total ordering on a class
>and its superclasses, but the only characteriztion of it that I know of is
>that the CPL is the total ordering computed by the algorithm. That
>algorithm is understandable at the operational level, but there is no easy
>characterization of it.
I think what most programmers want is a two sentence explanation of how
inheritance works in CLOS. The equivalent for Smalltalk is:
Child classes get all the methods and all the slots of
their parents. Any methods defined with the same name
as the parent defined in the child override the parent's
method.
I propose this for CLOS:
The inheritance graph is searched depth first, left to
right, up to joins. Superclasses at joins are placed
in the class precedence list at the last occurance,
rather than the first, since such superclasses are
usually more general than their subclasses, and classes
at the end of the class precedence list should be more
general than those at the beginning. The qualitative
effect is to achieve a linearization of the inheritance
graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph.
Well, that's three sentences, but I think most people won't mind.
A more detailed explantion should go into what can go wrong. The
Ducournau and Habib paper discusses this in a more formal way.
The essense is that if two or more subclasses share two
or more join superclasses, then the algorithm can fail.
In such cases, the two join superclasses are two alternative end
elements for the sublist CPL containing the subclasses, so there
is no unique linearization. Scherlis's comments about programmer
hooks at the Palo Alto meeting might be appropriate here, since
the programmer could choose which join superclass is more
general, but I think the appropriate place to put in these hooks
is the metaobject protocol, and not something like prompting the
programmer.
>Intellectual honesty compels me to point out things like this when
>I address an audience. I suppose it annoys people when I do that,
>but maybe we should give some thought to designing a language such that
>there are few oppurtunities for ``Gabriel's inevitable critique.''
I have no problem with such critiques, however, I think at some point
we need to iterate to a design which we all feel comfortable with,
and which application developers can use. My impression of the
inheritance algorithm is that it refines and solidifies current practice
which is *precisely* what a standard should do. Whether or not it
is the ultimate in linguistic software reuse mechanisms is another
question. I don't think it is, but until I know the answer, have
tested it with a couple of applications, and have discussed it extensively
with other people, I'm sure not going to recommend that it be made a
standard.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1327 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:26:44 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:25:13 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:24:51 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:25:28 pdt
Date: Thu, 9 Jul 87 13:25:28 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092025.AA22144@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Category Errors
>
> 1. Let sea of classes/metaclasses remain a miasma and inform
> programmer that he ought not mix things up.
>
> 2. Define a notion of class category or classs level and have a
> category of generic function for each class category.
This is a difficult one, and relates to Patrick's goal of maintaining metaclass
protocol and class protocol orthogonally. Pros are that it can avoid having
programmers make mistakes like defining MAKE-INSTANCE on a class, as cited
in the base note, cons are that a programmer might actually *want* to have
a particular class be instantiated slightly differently. Given Lisp's
tendency to allow a programmer to do anything, as long as the name for
doing it can be found, I think 1) should be the choice, except the "sea
of classes/metaclasses" ought probably to be broken up into little bays
and gulfs via. the package system. With some method names (like MAKE-INSTANCE)
there is no hope, since they are firmly in the programmer interface.
With the rest of the metaobject protocol, the names should be exported
from a seperate package, so that only programmers who want to do metaclass
programming need be concerned with them. One can reasonably argue that
a programmer using CLOS should be familar enough with the programmer
interface functions to be able to avoid an accidental redefinition of
the methods there, but we should certainly not require CLOS programmers
to be familar with metaclass names unless they intend to do metaclass
programming.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1329 kempf%hplabsz@hplabs.HP.COM Re: First Try at Terminology
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:29:00 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:27:28 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:27:01 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:27:41 pdt
Date: Thu, 9 Jul 87 13:27:41 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092027.AA22154@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: First Try at Terminology
>The definition of a situation is designed to cover function invocations,
>macro calls, and instances of the use of special forms as well as
>conditions that might arise within a running CLOS system. A situation is
>not a purely syntactic state of affairs, because the preconditions for an
>error usually requires that something about the nature of the arguments
>to a function, for example, be known. The wording of these definitions will
>need further work.
Why not go one step further and use preconditions
and postconditions on the functions and macros, ala` Hoare logic?
Example from 87-002 spec (RET is the returned value, ARG the argument):
CLASS-OF
Pre: T
Post: RET is an element of C, the set of defined classes, if ARG is an
instance of a class | error
The postconditions could contain error postconditions of three types:
1) errors at all optimization levels (1 in the original message)
2) errors at the lowest only (2 in the orignal message)
3) errors which implementations are permitted to extend CLOS to
cover.
>I believe we wish to control where extensions to CLOS are allowed to occur.
>The first four terms are designed to control semantic extensions while the
>fifth is designed to control syntactic extensions, which are somewhat
>different.
Yes, this is a laudable goal, but I fear that any attempt to do this
in English may remain open to ambiguous interpretation.
>I believe we want to define precise terms such as these and use them
>exactly in the CLOS specification so that, rather than the CLOS
>specification being a pseudo-user's-guide as CLtL is, it can be a
>specification suitable for an implementor.
100% agreement. Barring any agreement on more rigorous formalism, I
can live with the terminology in the base note. It's a whole lot better
than CLtL.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1333 kempf%hplabsz@hplabs.HP.COM Re: Metaclass Protocol Goals
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:32:33 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 13:30:54 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 13:30:20 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 13:30:59 pdt
Date: Thu, 9 Jul 87 13:30:59 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092030.AA22198@hplabsz.hpl.hp.com>
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Metaclass Protocol Goals
Patrick's design rationale looks like a good beginning, and would be a good
addition to the beginning of 87-003, as motivation for the metaclass
protocol. I had a couple of comments and questions:
>Class behavior and instance behavior are othorgonal in CLOS. The
>metaclass protocol must preserve this orthoganality.
I'm not quite sure I understand what you mean by class and instance
behavior being orthogoal. Since class objects are instances of
the metaclass, this statement would seem not to be true for classes
when considered as instances.
>- The side effects on CLOS objects (Classes, generic-functions, methods)
>that spead across object links should be exposed.
>Compute-class-precedence-list is a good example.
I'm not sure I understand what you mean by "be exposed". What I
think you mean by "side effects on CLOS objects that spread across
object links" is protocols which affect objects whose structure acts
as templates for other objects (is that so?). As an example, the
structure of a class object acts as a template for instances. If
you mean that methods affecting the structure of such "template
objects" should be included in the public metaobject protocol, then
I agree.
>- It should be possible to access some exposed slots of a CLOS object
>without side-effect.
I agree with this, but I think it might be difficult to achieve in
practice. With method combination, it should be possible for the designer
of a metaclass to define a daemon method on any method in the protocol
which cause side effects to occur. I can think of a couple solutions to
this off the top of my head. One is to suggest that metaclass programmers
follow a convention of not defining daemon methods which cause side
effects, another is to specifically forbid defining daemon methods on
metaclass methods, possibly through a declaration mechanism (as I
suggested in an earlier note this spring). Probably the former is better,
since daemon methods for doing things like updating browsers when
classes are defined might be useful.
>- We probably need to care about the compile environment. We don't have
>to specify what it is but where, in our protocol it should be looked up
>or side effected. At least we must make sure that we don't go against
>the following statements:
>1)Compile-file does not side effect the running environment.
>2)It is possible to implement a cross loader (Something that loads files
>in order to make some class definitions, etc that will affect
>the compilation but not the running environment).
Given the design of the Common Lisp, this might be very
difficult to achieve. Using the PCLOS implementation from Gregor,
I tried a quick and dirty implementation of a seperate compile time
namespace for CommonObjects on CLOS and ran into some serious problems.
Basically, for languages such as CommonObjects which compute alot of
their inheritance information at compile time, the only alternative
to side effecting the compile time environment is to somehow maintain
the information and update global structures only when its safe. This
approach is used in our native code CommonObjects implementation, and
it is expensive. The CommonObjects on CLOS compiles about twice as
fast because it just side effects the compile time environment. In the
CLOS language, if attention is not paid to side effects, then classes
need to be defined in the compile time environment so that method
definintions being defined in the same file (a logical way to organize
a body of software) can be compiled.
Aside from problems with bootstrapping CLOS itself (which Gregor
seems to pretty well have under control in the portable implementation),
much of the reason for not side effecting the compile time environment
goes away with multiple virtual address spaces. A "spoiled" compile
time environment can just be thrown away. Of course, this doesn't
solve the problem for machines where multiple virtual address spaces
are not an option.
Jim Kempf kempf@hplabs.hp.com
∂09-Jul-87 1355 Kahn.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 13:55:05 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 09 JUL 87 13:49:06 PDT
Date: Thu, 9 Jul 87 13:48:39 PDT
From: Ken Kahn <Kahn.pa@Xerox.COM>
Subject: Re: Category Errors
In-Reply-To: <8707092025.AA22144@hplabsz.hpl.hp.com>
To: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870709-134906-4431@Xerox>
I think it would be a mistake to build barriers between class and
metaclass protocols. One of the strong appeals of CLOS is that one can
experiment within its framework. We once worked out how Object Lisp's
view that classes and instances are pretty much the same could be
implemented in PCL. A good fraction of the OOP community believes in
these "prototypes" which unify classes and instances. We should be
careful not to prohibit CLOS from evolving in that direction if people
come to believe its a win.
References
kempf%hplabsz@hplabs.HP.COM's message of Thu, 9 Jul 87 13:25:28 PDT --
Re: Category Errors
∂09-Jul-87 1431 kempf%hplabsz@hplabs.HP.COM Re: Category Errors
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 14:31:26 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Thu, 9 Jul 87 14:28:00 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Thu, 9 Jul 87 14:27:40 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Thu, 9 Jul 87 14:28:20 pdt
Date: Thu, 9 Jul 87 14:28:20 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8707092128.AA22639@hplabsz.hpl.hp.com>
To: Kahn.pa@Xerox.COM, kempf%hplabsz@hplabs.HP.COM
Subject: Re: Category Errors
Cc: common-lisp-object-system@sail.stanford.edu
>I think it would be a mistake to build barriers between class and
>metaclass protocols. One of the strong appeals of CLOS is that one can
>experiment within its framework. We once worked out how Object Lisp's
>view that classes and instances are pretty much the same could be
>implemented in PCL. A good fraction of the OOP community believes in
>these "prototypes" which unify classes and instances. We should be
>careful not to prohibit CLOS from evolving in that direction if people
>come to believe its a win.
>
I agree with this viewpoint in principle, which is why I wouldn't want
to see any stronger barriers be erected than packageization. That seems
to me to be the minimum to keep people happy who want to maintain some
distance and are already uncomfortable with the metaclass protocol,
and those who believe that no barriers are appropriate. Someone wanting
to implement Object Lisp need only use both the user interface and
metaclass symbols.
∂09-Jul-87 1933 Bobrow.pa@Xerox.COM Re: Metaclass Protocol Goals
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Jul 87 19:32:59 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 JUL 87 19:03:04 PDT
Date: 9 Jul 87 19:03 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Metaclass Protocol Goals
In-reply-to: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>'s message of Thu, 9
Jul 87 13:30:59 pdt
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870709-190304-4903@Xerox>
Patrick>- It should be possible to access some exposed slots of a
CLOS
object >without side-effect.
Jim> I agree with this, but I think it might be difficult to achieve
...
It is not difficult to document for CLOS. If a package adds behavior to
CLOS, then a user of that package should document its behavior. This is
not a matter for program control -- just for social control.
∂10-Jul-87 1026 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 10 Jul 87 10:25:57 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae21575; 10 Jul 87 11:54 EDT
Received: from ti-csl by RELAY.CS.NET id ag17093; 10 Jul 87 11:47 EDT
Received: from Jenner by tilde id AA26237; Fri, 10 Jul 87 10:04:49 CDT
Message-Id: <2761916421-9049515@Jenner>
Date: Fri, 10 Jul 87 10:00:21 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 9 Jul 87 11:51 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
Date: 9 Jul 87 11:51 PDT
From: Danny Bobrow <Bobrow.pa@xerox.com>
Subject: Re: Class redefinition and class-changed.
Goals:
- There should be a way to define a method for class-changed
on the obsolete class and the class.
- This method needs to be defined before any the instances is
changed, otherwise it wouldn't get invoked on all the instances of
the class.
Agreed.
The necessary and sufficient condition for this is to be able to get
hold of an obsolete version of a class.
I don't agree. We said in chapter 1 that the updating of the instances is done
at an implementation-dependent time. It means that unless you prepare your
methods in advance (before the class is actually redefined) you are going to let
some instances be updated without proper class-changed method invokation. The
worst part is you may not find out about it. A necessary condition is to be
able to get hold of an obsolete version of a class before the class is changed.
Proposal:
Changing a class updates a database to allow the following generic
functions to work.
GET-OBSOLETE-VERSION class
returns the preceding obsolete version of this class, or NIL if none.
This allows users to define methods at any time on the obsolete class.
Obsolete classes themselves may also have an obsolete-version. Obsolete
classes also respond to
GET-UPDATED-VERSION obsolete-class
with the next class or NIL
This allows following the chain in the opposite direction
I don't have much objection to this. However, I don't see it as sufficient to
implement the goals you agreed upon. I see your proposal as a complement to
mine.
(let ((obsolete-class
(cdr (assoc class (GET-OBSOLETE-CLASSES-FOR-REDEFINITION class )))))
Add method on class-changes....
redefine the class class ...
(eq obsolete-class (GET-OBSOLETE-VERSION class)))
=> T
Patrick.
∂13-Jul-87 1039 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Metaclass Protocol Goals
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 13 Jul 87 10:39:10 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad17106; 13 Jul 87 13:12 EDT
Received: from ti-csl by RELAY.CS.NET id an13899; 13 Jul 87 13:05 EDT
Received: from Jenner by tilde id AA06513; Fri, 10 Jul 87 16:44:10 CDT
Message-Id: <2761940409-10490738@Jenner>
Date: Fri, 10 Jul 87 16:40:09 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Metaclass Protocol Goals
In-Reply-To: Msg of Thu, 9 Jul 87 13:30:59 pdt from Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Patrick's design rationale looks like a good beginning, and would be a good
addition to the beginning of 87-003, as motivation for the metaclass
protocol. I had a couple of comments and questions:
Thank you for your comments.
>Class behavior and instance behavior are othorgonal in CLOS. The
>metaclass protocol must preserve this orthoganality.
I'm not quite sure I understand what you mean by class and instance
behavior being orthogoal. Since class objects are instances of
the metaclass, this statement would seem not to be true for classes
when considered as instances.
What I meant is that the metaclass does affect the way classes parse their
defclass, compute class precedence list, gather their slots... all these things
are class business. On the other hand, it affects how instances are allocated,
laid out, accessed. That's instance business. These two sorts of businesses are
independent. I may want to keep a CLOS Syntax, CPL, etc, but have my instances
represented differently. I may want to define a FLAVOR metaclass and
represent its instances the way the default CLOS metaclass represents them.
>- The side effects on CLOS objects (Classes, generic-functions, methods)
>that spread across object links should be exposed.
>Compute-class-precedence-list is a good example.
I'm not sure I understand what you mean by "be exposed". What I
think you mean by "side effects on CLOS objects that spread across
object links" is protocols which affect objects whose structure acts
as templates for other objects (is that so?). As an example, the
structure of a class object acts as a template for instances. If
you mean that methods affecting the structure of such "template
objects" should be included in the public metaobject protocol, then
I agree.
Exposed means documented (what it is), with a protocol that goes with it (what
you can do, how you do it).
"Side effects on CLOS objects that spread across object links" means the side
effects that affect some other objects, not just the one you intended to
side-effect. For example, if you redefine a class, you are likely to affect
other classes besides the one you are redefining. These side effects are
particularly important to specify because they can spread across metaclasses.
If metaclass A handles class redefinition one way and metaclass B handles it in
a different way, then clearly we have a problem if we can mix classes of A with
classes of B.
>- It should be possible to access some exposed slots of a CLOS object
>without side-effect.
I agree with this, but I think it might be difficult to achieve in
practice. With method combination, it should be possible for the designer
of a metaclass to define a daemon method on any method in the protocol
which cause side effects to occur. I can think of a couple solutions to
this off the top of my head. One is to suggest that metaclass programmers
follow a convention of not defining daemon methods which cause side
effects, another is to specifically forbid defining daemon methods on
metaclass methods, possibly through a declaration mechanism (as I
suggested in an earlier note this spring). Probably the former is better,
since daemon methods for doing things like updating browsers when
classes are defined might be useful.
We define a protocol, not a language. A protocol is a set of rules that someone
must observe in order to preserve the integrity of the system. If we say "This
should be side effect free", it means that someone writing a new metaclass must
satisfy this constraint if he expect CLOS to continue working right. We
certainly don't want to do anything complicated to enforce it.
>- We probably need to care about the compile environment. We don't have
>to specify what it is but where, in our protocol it should be looked up
>or side effected. At least we must make sure that we don't go against
>the following statements:
>1)Compile-file does not side effect the running environment.
>2)It is possible to implement a cross loader (Something that loads files
>in order to make some class definitions, etc that will affect
>the compilation but not the running environment).
What I was trying to say here is we must define provision for implementations to
do a good job of defining a compilation environment, not to require it.
Using the PCLOS implementation from Gregor,
I tried a quick and dirty implementation of a seperate compile time
namespace for CommonObjects on CLOS and ran into some serious problems.
Running into problems because the implementation does not allow you to do it is
one thing, running into problems because the metaclass protocol makes it
impossible is another thing.
Patrick.
∂15-Jul-87 1000 kempf%hplabsz@hplabs.HP.COM Re: Class redefinition and class-changed.
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Jul 87 10:00:19 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Wed, 15 Jul 87 09:58:27 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Wed, 15 Jul 87 09:58:07 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Wed, 15 Jul 87 10:58:34 pdt
Message-Id: <8707151658.AA08774@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Your message of Fri, 10 Jul 87 10:00:21 CDT.
<2761916421-9049515@Jenner>
Date: Wed, 15 Jul 87 10:58:31 -0700
From: kempf%hplabsz@hplabs.HP.COM
> GET-OBSOLETE-VERSION class
> returns the preceding obsolete version of this class, or NIL if none.
> This allows users to define methods at any time on the obsolete class.
> Obsolete classes themselves may also have an obsolete-version. Obsolete
> classes also respond to
Is this meant to imply that there can be multiple versions of classes
floating about? If so, then perhaps class versioning needs to be
investigated more closely.
Jim Kempf kempf@hplabs.hp.com
∂16-Jul-87 0752 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 16 Jul 87 07:52:13 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab01711; 16 Jul 87 10:24 EDT
Received: from ti-csl by RELAY.CS.NET id ac00916; 16 Jul 87 10:17 EDT
Received: from Jenner by tilde id AA07022; Thu, 16 Jul 87 08:00:48 CDT
Message-Id: <2762427556-15862063@Jenner>
Date: Thu, 16 Jul 87 07:59:16 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of Wed, 15 Jul 87 10:58:31 -0700 from kempf%hplabsz@hplabs.hp.com
> GET-OBSOLETE-VERSION class
> returns the preceding obsolete version of this class, or NIL if none.
> This allows users to define methods at any time on the obsolete class.
> Obsolete classes themselves may also have an obsolete-version. Obsolete
> classes also respond to
Is this meant to imply that there can be multiple versions of classes
floating about? If so, then perhaps class versioning needs to be
investigated more closely.
I am not sure I agree with the term VERSION. An obsolete class object
is not a version of the class because it is here just to support the
class-changed protocol. It is not meant to have permanent instances.
Surrogate might be more appropriate. In the sense there can only be
instances of "current class" outside of the execution of CLASS-CHANGED,
I don't think we need to worry about class versioning.
Patrick.
∂22-Jul-87 0639 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 22 Jul 87 06:39:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa18126; 22 Jul 87 9:35 EDT
Received: from ti-csl by RELAY.CS.NET id ab14379; 22 Jul 87 9:31 EDT
Received: from Jenner by tilde id AA23150; Wed, 22 Jul 87 07:33:54 CDT
Message-Id: <2762944528-5369042@Jenner>
Date: Wed, 22 Jul 87 07:35:28 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Category Errors
In-Reply-To: Msg of 08 Jul 87 0938 PDT from Dick Gabriel <RPG@sail.stanford.edu>
From Gabriel:
One minor point that came up at the Symbolics meeting last Thursday
was category errors and whether we should try to outlaw them somehow.
Here is an example of a category error:
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
(make-instance (class-prototype (class-named 'apple-pie)) ...)
Here someone would be making a category error by defining a method on
MAKE-INSTANCE at the wrong level - the class level. What makes this easy
for a programmer to do this is the availability of CLASS-PROTOTYPE.
However, it is never hard to do because the programmer can write:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
to get his class prototype.
We have two alternatives:
1. Let sea of classes/metaclasses remain a miasma and inform
programmer that he ought not mix things up.
2. Define a notion of class category or classs level and have a
category of generic function for each class category.
From Ken Kahn:
I think it would be a mistake to build barriers between class and
metaclass protocols. One of the strong appeals of CLOS is that one can
experiment within its framework. We once worked out how Object Lisp's
view that classes and instances are pretty much the same could be
implemented in PCL. A good fraction of the OOP community believes in
these "prototypes" which unify classes and instances. We should be
careful not to prohibit CLOS from evolving in that direction if people
come to believe its a win.
I kind of agree with both Dick's and ken's concerns. The user should be
able to do metaclass programming if he wants to but this should be an
intent, not an accident. CLASS-PROTOTYPE working for standard-classes
is a good example of something intended to be used for metaclass
programming but works also for non metaclass classes.
I propose the following in order to categorize metaclass programming and
class programming:
CLASS
|
STANDARD-CLASS
|
METACLASS-CLASS
Now, all metaclass objects are instances of METACLASS-CLASS instead of
STANDARD-CLASS. This is to say that standard-class can be defined like:
(defclass STANDARD-CLASS (CLASS)
<slots>
(:metaclass METACLASS-CLASS))
STANDARD-CLASS does not support metclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
Somebody defining a new metaclass (or wanting to do metaclass
programming with his objects) will use METACLASS-CLASS as metaclass. It
will be a conscious decision.
The make-instance problem still exists but will not arise by accident,
somebody will have to do a trick like:
(defvar *apple-pie-prototype* (make-instance 'apple-pie))
and will probably get what he deserves.
Patrick.
∂22-Jul-87 1014 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Jul 87 10:13:59 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 196114; Tue 21-Jul-87 12:35:38 EDT
Date: Tue, 21 Jul 87 12:35 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Jul 87 12:38 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870721123511.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 08 Jul 87 0938 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Suppose that MAKE-INSTANCE is a generic function. Its definition
might look like this:
(defmethod make-instance ((class standard-class) &rest args)...)
Notice that the class of the argument CLASS is STANDARD-CLASS, which
indicates that the operation of MAKE-INSTANCE is controlled at the
meta-object level. Suppose someone were to write:
(defmethod make-instance ((class apple-pie) &rest args)...)
I don't think this is fundamentally different from someone defining
a method on spaceships for a generic function that is only supposed to
be used with windows. The only reason I can see that confusion between
classes and metaclasses seems worse than confusion between spaceships
and windows is that metaclasses are less familiar.
If we didn't want to follow the usual Lisp philosophy of giving the
user enough rope to hang himself, we could add a feature such as the
following
(defgeneric-options make-instance (class &rest initargs)
(:parameter-specializer-restriction class (or class symbol)))
which says methods can't be defined with a parameter specializer for
the first parameter (named class) that isn't a subtype of (or class symbol).
Using the type system to express the restriction, rather than inventing
a new concept of levels, seems both more general and easier to understand.
However, I don't really think we want to add this kind of restriction, at
least, it wouldn't be consistent with the minimalist design criterion
we have used elsewhere in CLOS.
∂23-Jul-87 1812 Gregor.pa@Xerox.COM initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 18:12:34 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 23 JUL 87 18:11:32 PDT
Date: Thu, 23 Jul 87 18:09 PDT
From: Gregor.pa@Xerox.COM
Subject: initialization meeting notes
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
In this message I try to summarize what we agreed at the meeting in
Boston. The basis for this message is the 4 pages of notes which Sonya
took and which Sonya, Dave and I went over just before the meeting
ended. I have tried to include in this message only what we actually
agreed on. I will send out my comments and suggestions in a separate
message.
First, a brief summary of what we agreed:
- there will be a :initarg slot option
- will will support remote initarg defaulting by having an
defclass option like :default-initargs.
- there will be a procedural model of how the whole thing
works. Extensions to initialization behavior other than
simple-slot-filling-initargs and initarg-remote-defaulting
will be done by defining a method on the appropriate generic
function.
Another important thing which we agreed is that we are going to have to
go back and re-examine our rules for argument list congruence. The
existing rules clearly get in our way for doing initialization. In a
separate message I will try to summarize those problems.
In the meeting, we put up some code for make-instance and
initialize-instance. I am including that here:
(defmethod make-instance ((class-name 'symbol) &rest initargs)
(apply #'make-instance (class-named class-name) initargs))
(defmethod make-instance ((class standard-class) &rest initargs)
(let* ((proto (class-prototype class))
(defaulted-initargs (default-initargs proto initargs)))
(check-initargs class defaulted-initargs)
(let ((instance (apply #'allocate-instance class defaulted-initargs)))
(apply #'initialize-instance instance defaulted-initargs)
instance)))
(defmethod initialize-instance ((obj object) &rest initargs)
;; The default initialize-instance method deals with setting the
;; values of slots from slot-filling-initargs and from initforms.
;;
;; The rules are that the leftmost initarg which is declared
;; as setting a slot (with the :initarg slot option) actually
;; does set it (or is it the rightmost?); and that slots which
;; are not set by an initarg have their :initform evaluated and
;; used to set them.
)
An effect of putting the slot setting stuff in the default method on
initialize-instance is that most programmers will want to define their
initialize-instance methods as :after methods. This means an instance
will get initialized in order from most general to least general.
The default method for default-initargs implements the initarg remote
defaulting behavior using the :default-initargs class option.
The default method for check-initargs checks the validity of the
initargs by checking two sources:
1. an initarg is valid if it is specified as a slot-filling initarg.
2. an initarg is valid if it is specified as a &key argument in
one of the applicable methods on initialize-instance.
Here is an example of a use of this protocol:
(defclass ship ()
((x :initarg :x)
(y :initarg :y)))
(defmethod initialize-instance :after ((s ship) &key startp)
(when startp (start s)))
(defmethod start ((s ship))
(with-slots ((s :use-accesors nil))
(if (and x y)
<start it up>
(error "Have to set X and Y before starting a ship."))))
(defclass homing-ship (ship)
()
(:default-initargs
:x 0
:y 0))
(defmethod home ((s homing-ship))
(with-slots ((s :use-accessors nil))
(setq x 0 y 0)))
We also agreed that there would be documented functions for finding out
about the initargs that set slots for a class and also finding out about
the default initargs for a class. This doesn't seem to be too hard;
the only serious problem has to do with arranging for a the default
initarg value forms to be evaluated in the lexical environment of the
defclass. (Of course if environments were first class objects this would
be trivial...)
-------
∂23-Jul-87 1917 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 19:16:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JUL 87 19:16:02 PDT
Date: 23 Jul 87 19:15 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 21 Jul 87 12:35 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870723-191602-1486@Xerox>
I don't think this is fundamentally different from someone
defining a method on spaceships for a generic function that is only
supposed to be used with windows. The only reason I can see that
confusion between classes and metaclasses seems worse than
confusion between spaceships and windows is that metaclasses are
less familiar.
I think this is exactly right.
If we didn't want to follow the usual Lisp philosophy of giving
the user enough rope to hang himself,
Leave the rope. We don't put strong typing in Lisp either.
danny
∂23-Jul-87 1941 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 23 Jul 87 19:41:29 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 23 JUL 87 19:41:10 PDT
Date: 23 Jul 87 19:41 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 10 Jul 87 10:00:21 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870723-194110-1523@Xerox>
The necessary and sufficient condition for this is to
be able to get hold of an obsolete version of a class.
I don't agree. We said in chapter 1 that the updating of the
instances is done at an implementation-dependent time.
I agree that your arguments imply your conclusion. I think however,
that it would be better to say that "updating of the
instances is done at an implementation-dependent time sometime after the
class is redefined." Since this is really an environment support
feature, I think we should specify that it will not occur before the
first method on an obsolete instance is called.
danny
∂24-Jul-87 0623 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 06:23:14 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa05351; 24 Jul 87 9:23 EDT
Received: from ti-csl by RELAY.CS.NET id aa06359; 24 Jul 87 9:16 EDT
Received: from Jenner by tilde id AA01610; Fri, 24 Jul 87 07:33:49 CDT
Message-Id: <2763117294-15749125@Jenner>
Date: Fri, 24 Jul 87 07:34:54 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 23 Jul 87 19:41 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
I agree that your arguments imply your conclusion. I think however,
that it would be better to say that "updating of the
instances is done at an implementation-dependent time sometime after the
class is redefined." Since this is really an environment support
feature, I think we should specify that it will not occur before the
first method on an obsolete instance is called.
I see two problems with this approach:
- How would the environment guess that a class-changed method will (or will not)
be defined?
- Even if you see it as an environment support, we need to specify this support
at the metaclass level since class redefinition will be specified. I don't think
we can afford to leave holes like that in the metaclass protocol.
Patrick.
∂24-Jul-87 0854 Bobrow.pa@Xerox.COM Re: Class redefinition and class-changed.
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Jul 87 08:54:27 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 JUL 87 08:51:47 PDT
Date: 24 Jul 87 08:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class redefinition and class-changed.
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 24 Jul 87 07:34:54 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: Bobrow.pa@Xerox.COM, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870724-085147-2517@Xerox>
I think we should specify that instance updating will
not occur before the first method on an obsolete instance is
called.
I see two problems with this approach:
- How would the environment guess that a class-changed method
will (or will not) be defined?
It doesn't have to guess. If the class changed method is defined before
any any method is called on an obsolete instance, it will be used.
Otherwise not. Hence users should define such class-changed methods
immediately (soon) after redefining the class.
- Even if you see it as an environment support, we need to
specify this support at the metaclass level since class
redefinition will be specified. I don't think we can afford to
leave holes like that in the metaclass protocol.
The meta-object support necessary is to provide a mechanism to obtain
the obsolete class so that class-changed methods can be defined, and to
specify when these methods can be defined in order to effect all
instances that need to be updated.
danny
∂24-Jul-87 1133 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 11:33:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198616; Fri 24-Jul-87 14:34:24 EDT
Date: Fri, 24 Jul 87 14:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2762944528-5369042@Jenner>
Message-ID: <870724143345.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 22 Jul 87 07:35:28 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
....
I propose the following in order to categorize metaclass programming and
class programming:
CLASS
|
STANDARD-CLASS
|
METACLASS-CLASS
Now, all metaclass objects are instances of METACLASS-CLASS instead of
STANDARD-CLASS. This is to say that standard-class can be defined like:
(defclass STANDARD-CLASS (CLASS)
<slots>
(:metaclass METACLASS-CLASS))
I believe this is a good suggestion. That is, it appeals to my aesthetic
sense, although I have not been able to come up with any specific programming
activities that require it.
STANDARD-CLASS does not support metaclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
This part, however, won't work. As I understand it, CLASS-PROTOTYPE has
to work on all classes, because of the way the generic function dispatching
in the initialization protocol is going to work. We still haven't nailed
down the initialization protocol, but I think the part of it we all seem
to agree on already requires all classes to have a prototype.
Similarly, functions like CLASS-DIRECT-SUPERCLASSES are part of metaclass
programming, but that doesn't mean they are only applicable to metaclasses.
They are applicable to all classes.
∂24-Jul-87 1136 RPG Category Errors
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``I don't think this is fundamentally different from someone defining a
method on spaceships for a generic function that is only supposed to be
used with windows.''
Danny replies:
``I think this is exactly right.''
As I mentioned in my note, I don't care that this blemish appears in CLOS,
but I do insist that we understand that reasonable people will consider it
to be a blemish. The reason for this is also the reason that Danny's reply
is incorrect. The differences between someone writing a method on
spaceships for a generic function that is only supposed to be used with
windows and someone writing a method on a base-level class for the generic
function MAKE-INSTANCE are these:
1. MAKE-INSTANCE is a generic function defined in CLOS, and we
have the ability to enforce the user not making this sort of
error. We've carefully laid out, in most cases, the range of
legal arguments to functions and generic functions in CLOS; we
could easily do that here, whereas it's difficult to control a
user who wants to act irrationally with code all of his own
invention.
2. Mistakenly writing methods for some class not intended to be
the subject of the generic function by the author of that
generic function is most likely a user-level semantic error,
while defining a method on a class where the person defining
the generic function intends methods to be on meta-classes is a
category error - that's why I called it a ``category error''
rather than a ``source of potential user bugs.'' The error lies
in confusing two levels of classes defined in CLOS rather than
in confusing two classes defined by a user.
My point was that one could rationally design CLOS to be able to
distinguish between classes and meta-classes, and hence we would be
justified in trying to prevent category errors. Or we could choose not to
do that. I think that to dismiss the point as some fluke in thought
process before understanding the issues does ill justice to the
specification process, even though I believe we will allow the blemish.
-rpg-
∂24-Jul-87 1420 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:20:00 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 24 JUL 87 14:19:44 PDT
Date: 24 Jul 87 14:19 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 24 Jul 87
11:36 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870724-141944-3247@Xerox>
My point was that one could rationally design CLOS to be able
to distinguish between classes and meta-classes, and hence we would
be justified in trying to prevent category errors.
If it were clear that one could be sure that a definition were in error,
then perhaps we could consider enforcing some restrictions. However, it
is a rational thing to experiment with various new types of object
system, defining methods for all the protocol of interest, and not use
any preexisting class as a super-class (this is particularly a good idea
if one wants to make sure that the new implementation is complete). To
force a user to use a particular (perhaps empty) metaclass just for a
declaration surely violates the spirit of Lisp.
We've carefully laid out, in most cases, the range of
legal arguments to functions and generic functions in CLOS; we
could easily do that here, whereas it's difficult to control a
user who wants to act irrationally with code all of his own
invention.
We have NOT laid out the range of legal arguments for generic functions.
We have specified how they behave for arguments of particular classes;
tha is, we have described some method(s) on generic functions, and their
contract. A major point of object oriented programming is to allow
users to add their own methods to generic functions. To talk about THE
AUTHOR OF A GENERIC FUNCTION is to make the same mistake. Generic
functions have certain contracts, but not ones that restrict them to
certain classes of arguments.
I think that to dismiss the point as some fluke in thought
process before understanding the issues does ill justice to the
specification process, even though I believe we will allow the
blemish.
I think understanding the issue is important. So we agree on that
point. But I feel that the "blemish" is really a beauty mark.
danny
∂24-Jul-87 1421 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:21:16 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa10495; 24 Jul 87 17:10 EDT
Received: from ti-csl by RELAY.CS.NET id al08816; 24 Jul 87 17:04 EDT
Received: from Jenner by tilde id AA14079; Fri, 24 Jul 87 15:14:43 CDT
Message-Id: <2763144693-1137879@Jenner>
Date: Fri, 24 Jul 87 15:11:33 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Danny Bobrow <Bobrow.pa@XEROX.COM>
Cc: DUSSUD%Jenner%ti-csl.CSNet@RELAY.CS.NET,
common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of 24 Jul 87 08:48 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
Date: 24 Jul 87 08:48 PDT
From: Danny Bobrow <Bobrow.pa@xerox.com>
Subject: Re: Class redefinition and class-changed.
It doesn't have to guess. If the class changed method is defined before
any any method is called on an obsolete instance, it will be used.
Otherwise not. Hence users should define such class-changed methods
immediately (soon) after redefining the class.
In multiprocessing or interruptible environment, immediately is a weak
concept at best. You might get in a race condition with another
computation unit that touches instances. Furthermore, you can't prove
that some instances haven't been updated before you define the
changed-class method. How do you propose to solve this?
Patrick.
∂24-Jul-87 1427 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Category Errors
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:22:08 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah10487; 24 Jul 87 17:10 EDT
Received: from ti-csl by RELAY.CS.NET id am08816; 24 Jul 87 17:04 EDT
Received: from Jenner by tilde id AA14334; Fri, 24 Jul 87 15:24:33 CDT
Message-Id: <2763145381-1179246@Jenner>
Date: Fri, 24 Jul 87 15:23:01 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Category Errors
In-Reply-To: Msg of Fri, 24 Jul 87 14:33 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
STANDARD-CLASS does not support metaclass specific methods like
CLASS-PROTOTYPE, METACLASS-CLASS does.
This part, however, won't work. As I understand it, CLASS-PROTOTYPE has
to work on all classes, because of the way the generic function dispatching
in the initialization protocol is going to work. We still haven't nailed
down the initialization protocol, but I think the part of it we all seem
to agree on already requires all classes to have a prototype.
This is true, I forgot about it when I wrote this part.
Patrick.
∂24-Jul-87 1436 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:36:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198754; Fri 24-Jul-87 16:44:25 EDT
Date: Fri, 24 Jul 87 16:43 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: initialization meeting notes
To: Gregor.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Message-ID: <870724164346.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
There's a bunch of other stuff in the notes that didn't make it into
your message. Perhaps I'll send a summary of that in a later message,
but the most important thing right now from my point of view was a
statement (page 4) about open-coding which I think means that the
procedural model is to be done in such a way that it does not decrease
achievable performance of creating instances; in particular, the system
is allowed to recognize that the standard methods are being called for
make-instance of a particular class and use a different implementation
that produces equivalent results. This will have to be defined in more
precise language in the final specification, so that it is quite clear
what users can and cannot depend on.
∂24-Jul-87 1437 Moon@STONY-BROOK.SCRC.Symbolics.COM First Try at Terminology
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 24 Jul 87 14:36:59 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198777; Fri 24-Jul-87 17:02:52 EDT
Date: Fri, 24 Jul 87 17:02 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: First Try at Terminology
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 8 Jul 87 12:28 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870724170213.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I might quibble with one or two details, in particular the idea that it
is possible to prevent programmers from discovering and depending upon
what a particular implementation does in a particular undefined
situation, however on the whole this seems pretty good. I'd like to
see the terminology for erroneous situations tightened up for all of
Common Lisp, not just CLOS.
I don't think that it's the business of the CLOS subcommittee to do this.
In other words, I'm uncomfortable with the idea that "the CLOS
subcommittee of X3J13 is the only subcommittee that ever does anything"
(incidentally this is not quite true) implies that "the CLOS
subcommittee should do everything."
We can use a working terminology in our deliberations, but we should
be prepared to convert to whatever standard terminology is defined for
Common Lisp as a whole, when that happens. This suggests that we should
do something fairly simple and not develop an elaborate formalism.
Simply separating the cases of "an error is always signalled", "an error
is signalled unless you tell the compiler not to check for it", "the
effect is undefined", and "the effect is implementation-dependent"
seems sufficient to me.
∂24-Jul-87 1459 RPG Category Errors
To: common-lisp-object-system@SAIL.STANFORD.EDU
Danny says:
``We have NOT laid out the range of legal arguments for generic functions.''
My comment was:
``We've carefully laid out, in most cases, the range of legal arguments to
functions and generic functions in CLOS....''
I guess I shouldn't rely on subtle wording to get across a subtle point.
Here is a generic function ``in CLOS'':
Add-method generic-function method
And here is how we have ``carefully laid out ... the range of legal
arguments'' to it:
Arguments:
The generic-function argument is a generic function
object.
The method argument is a method object. The
lambda-list of the method function must be
congruent with the lambda-lists of any other
methods associated with the generic function and
with the lambda-list of the generic function.
(page 2-5, FUNCTIONS)
The thing in CLOS that is already the same sort of ``blemish'' as this
category error is discrimination on individuals. Blemish, beauty mark:
At least we can agree that in both cases an observer is justified in
thinking ``what's that thing?''
-rpg-
∂24-Jul-87 1645 RPG Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
The problem with class redefinition is that the updating of instances can
be caused by arbitrary events, as far as the user is concerned. If none of
DEFCLASS, ADD-METHOD, MAKE-METHOD, CLASS-NAMED, the evaluation of the
special form FUNCTION, and garbage collection can update instances, then
if a CLOS implementation does not have multitasking, the following will
work (or something like it):
(let ((obsolete-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,(class-named 'heh-heh))
#'...)))
If there is a CLOS implementation with all of the properties named
above except it does have multitasking (including incremental GC),
then some form or macro like ATOMICALLY wrapped around the above
will work.
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
I think, though, that it probably makes sense to have Danny's version
of GET-OBSOLETE-CLASS for the same reason that I don't like UNIX - it's
too easy to do a DEFCLASS of an existing class and then wish you
had a handle on the old one. I think we need to decide whether Patrick's
versions of getting obsolete classes are worth having around to simplify
life.
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
-rpg-
∂25-Jul-87 0719 Moon@STONY-BROOK.SCRC.Symbolics.COM Category Errors
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jul 87 07:19:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198981; Fri 24-Jul-87 22:34:00 EDT
Date: Fri, 24 Jul 87 22:33 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Category Errors
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 14:36 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870724223320.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
As a believer in open systems who doesn't think there should be distinctions
between system and user programs, I believe that Dick's arguments for defense
against defining bogus methods for MAKE-INSTANCE are equally as good
arguments for defense against defining bogus methods for any user-defined
generic function. Remember that not all user-written programs are used only
by their author.
Dick, would you agree that if CLOS removes this blemish, it should be done
with a mechanism that is easily accessible to the programmer-in-the-street?
My second point was that although I favor removing this blemish, CLOS currently
contains several other similar blemishes added in the name of simplicity
(example, no equivalent to Flavors' :required-methods defflavor option), so
I predict that we will end up leaving this blemish in. That's not an argument,
just an observation.
∂25-Jul-87 0720 Moon@STONY-BROOK.SCRC.Symbolics.COM Class redefinition and class-changed.
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 25 Jul 87 07:20:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 198991; Sat 25-Jul-87 01:27:15 EDT
Date: Sat, 25 Jul 87 01:26 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class redefinition and class-changed.
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2761765326-16486571@Jenner>,
<870709-115412-4166@Xerox>,
<2761916421-9049515@Jenner>,
<8707151658.AA08774@hplabsz.hpl.hp.com>,
<2762427556-15862063@Jenner>,
<870723-194110-1523@Xerox>,
<2763117294-15749125@Jenner>,
<870724-085147-2517@Xerox>,
<2763144693-1137879@Jenner>
Message-ID: <870725012629.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have several comments to offer on this conversation. I haven't managed
to organize the separate comments into as coherent a whole as I would like.
I believe Patrick's argument that it is necessary to define the
CLASS-CHANGED method -before- redefining the class. Symbolics has a lot of
experience with doing it the other way and it's unpleasant. I hope the
reasoning for this has been established now and doesn't need additional
argument (Danny, please speak up if you don't believe it yet).
I don't like Patrick's particular proposal, though.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is too complicated, because it
returns a whole alist rather than being just the primitive. In addition, I
don't think the set of "classes implicated in the class-redefinition of
CLASS" is computable until the details of the redefinition are known.
Suppose
(defclass one () (a b))
(defclass two (one) (c))
(defclass three (one) (d))
Now suppose we redefine one as follows:
(defclass one () (a b d))
Referring to the third paragraph on page 1-11 of 87-002, one and two are
"implicated", but three is not, or at least, whether three is implicated is
implementation-dependent. But if the new slot had been named e, both two
and three would have been implicated. I don't think the information in
Patrick's alist is needed anyway; when defining a method, one only defines
it for the obsolete class corresponding to one class. If a different
method needs to be defined for an obsolete subclass, the function can be
called again.
Thus I would replace Patrick's proposal with GET-OBSOLETE-CLASS-FOR-REDEFINITION
which takes one argument, a class, and returns one value, the obsolete class
that is a copy of the current definition of the class and will be used the next
time the class is redefined; this is created the first time you ask for it.
Perhaps GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION would be a better name.
As Danny proposed, a primitive to get the obsolete classes corresponding to
redefinitions that have already taken place is useful, for instance in case
you didn't realize ahead of time that you would need a CLASS-CHANGED method
and now want to patch up the program. I would suggest a function
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS which takes one argument, a
class, and returns one value, a list of obsolete classes, newest first.
There seems to be some confusion about how class redefinition works in CLOS
and what an "obsolete class" is. Let me restate what the 87-002 document
says in simpler language: Redefining a class never creates a new class
object to replace the existing class object; it always modifies the
existing class object. Thus there are no objects that exactly represent
"versions" of a class. There is also the concept of "obsolete instances",
which have dynamic extent and are created solely to pass as the first
argument to CLASS-CHANGED. When CLASS-CHANGED is called as a result of the
user calling CHANGE-CLASS, the obsolete instance is simply an instance of
the old class. When CLASS-CHANGED is called as a result of updating an
instance to reflect the latest definition of its class, the obsolete
instance contains the slot values of the un-updated instance and therefore
needs to have a class that has those slots: this is an "obsolete class".
An obsolete class is a copy of a class remembering the slots, methods, and
superclasses it had before it was redefined. Redefining a class only
creates an obsolete class when certain kinds of changes are made to the
class (see the third paragraph on page 1-11 of 87-002). For each past
version of a class that is sufficiently different from the current version,
there is an obsolete class object. Note that these are all obsolete versions
of the original class, they are not obsolete versions of each other.
Redefining a class also redefines subclasses of the class, so several
obsolete classes could be created. 87-002 doesn't say so, but I believe
the obsolete subclasses should be subclasses of the obsolete class and not
of the original class.
The second paragraph on page 1-12 of 87-002 could be interpreted as saying
that the only methods that are applicable to an obsolete instance I-sub-O
are the methods M-sub-C that were deleted from the class when it was
redefined. I do not believe this is what was intended--I believe we
intended to say that all methods that were applicable to instances of the
class before it was redefined are applicable to I-sub-O (unless additional
redefinitions have been done, for instance deleting those methods
entirely). If we really intended only deleted methods to be applicable, it
would be remarkably useless: for instance, deleted slots could be accessed
by normal means, but non-deleted slots could not be accessed except by
SLOT-VALUE, except in the case where the :ACCESSOR slot-option had been
removed. Again, in the x-y-rho-theta example, if methods for accessing
values that are conceptually slots but are not physically represented as
slots were not applicable, it would be necessary to violate modularity and
duplicate the functionality of those methods within the CLASS-CHANGED
method.
We have our choice of three ways to define what happens when a class is
redefined:
(1) A new class object is created, the name-to-class-object mapping is
changed, defclass-defined methods implied by the new definition are put on
the new class object, all methods other than defclass-defined methods that
apply to the old class are made to apply also to the new class, subclasses
of the old class are made to be subclasses of the new class instead, and
superclasses of the old class are made to be also superclasses of the new
class. If we had done this, there would have been an explicit
representation of versions of a class, and there would not have been any
concept of "obsolete classes."
(2) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, an anonymous obsolete class object is created, the modification is
propagated to subclasses which may create obsolete class objects for them
that are subclasses of the first obsolete class created, superclasses of
the original class are to be also superclasses of the obsolete class, and
all methods that applied to the original class are made to apply also to
the new class. (2) is what we did in 87-002. (2) is not simpler than (1),
but it has the advantage that classes maintain their identity as objects.
(3) There is a third way, which I will describe later in this message.
Referring again to the third paragraph on page 1-11 of 87-002, there is
another use for a primitive to get the obsolete class before redefining the
class. Not all redefinitions of a class call CHANGE-CLASS and
CLASS-CHANGED. Suppose someone changes a class in such a way that they
need to call a function to update each instance, but they have not actually
add, removed, or renamed slots. 87-002 does not provide any mechanism for
this. The programmer would probably resort to adding a dummy slot to force
instance updating. I think a better approach would be to specify that
calling GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION forces the next
redefinition of this class (directly or by redefining a superclass) to
update instances, even if it would not otherwise need to.
There are basically three approaches to the problem of writing a
CLASS-CHANGED method that updates an instance to reflect one particular
edit of the class's definition:
(1) Use the classes of the two arguments to CLASS-CHANGED to encode this
information. This is what the 87-002 document says, however it doesn't work.
(2) Use a third argument to CLASS-CHANGED to encode the information, such as
a sequence number saying how many times the class had been redefined. This
seems kludgey and was rejected in the past.
(3) Don't allow such precise control over instance updating in CLOS, instead
only allow CLASS-CHANGED methods that work for updates from -any- version of
the class to the current version. This is copping out, however it's practical,
since it's what Flavors does.
There are two reasons (1) doesn't work. First, 87-002 doesn't provide a way
to get the obsolete class for a particular edit, which you need in order to
define a method that applies specifically to that edit. This is what Patrick's
proposal addresses. Second, there is a problem when the class is redefined
multiple times. Suppose we do
(defclass foo () (a))
(defclass foo () (a b))
(defclass foo () (a b c))
(defclass foo () (a b c d))
and in connection with the third definition we need a CLASS-CHANGED method
to initialize the slot C. We don't want this method to be called for
instances that already have a slot C and are getting a slot D added, so we
want the method to specialize its first parameter as well as its second.
The problem is that CLOS has no way to define one method that applies to the
first and second obsolete classes, but not to the third obsolete class. In
order to define this method, we have to know the exact editing history of
the class FOO, which seems unreasonable. We can't fix this by making the
second obsolete class a subclass of the first obsolete class, because if
the user removes a slot we would have a class that has fewer slots than its
superclass, which CLOS does not allow. We could call
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS to get the entire list of
obsolete classes for the class FOO, and then we could iterate over that
list seeing which obsolete classes had a slot C and which didn't, and
define CLASS-CHANGED methods accordingly, but this starts to look like an
elaborate rigamarole for something that should have been simple.
The above assumes that we believe what page 1-12 of 87-002 implies, namely
that instances are updated directly to the latest version of the class
("the second argument is an instance of the class C"). Alternatively, we
could specify that "ontogeny recapitulates phylogeny" and the instance is
repeatedly updated one step at a time, until it reaches the current
definition of its class. In the FOO example above, we would define the
CLASS-CHANGED method that initializes C to specialize its first parameter
to the second obsolete class, with confidence that instances of the
original FOO would first get a slot B, then would get a slot C, then would
get a slot D, and in the second of the three steps, our method would be
called.
This means that -both- arguments to CLASS-CHANGED could be instances of
obsolete classes. It also means that our CLASS-CHANGED method can't
specialize its second parameter, because at first that will be the class
FOO, but after FOO is redefined again, it will be an obsolete class. If we
don't specialize the second parameter, it seems we could be confused by
CLASS-CHANGED being called when CHANGE-CLASS was used to change an instance
of FOO into an instance of BAR. This is not a problem if CHANGE-CLASS,
like all other generic functions, first updates its argument to the latest
definition of its class, before changing it to the new class; then a method
specialized to an obsolete class in its first parameter can never be called
with the second parameter an instance of anything other than the next newer
version of the same class. This all seems slightly kludgey, but does seem
like it should work.
Is there any chance of garbage collecting all these obsolete classes when
there are no longer any instances that haven't been updated yet? We'd also
like to garbage collect the data structures required to make methods
applicable to the original class also applicable to the obsolete class.
I doubt it's possible to GC this stuff, the whole data structure seems too
interconnected.
The third way to define what happens when a class is redefined, mentioned
earlier, is as follows: Don't try to use CLASS-CHANGED for both changing
the class of an instance and updating an instance to a new version of its
class. Invent a new generic function CLASS-REDEFINED, which is called when
an instance is updated to a new version of its class. This avoids the
complicated concept of "obsolete classes", at the cost of conveying the
former state of the instance in a less object-oriented fashion. Perhaps
CLASS-REDEFINED would receive three arguments: an instance of the class,
already updated to the latest definition of the class, a property list
associating slot names to slot values, with one entry for each slot that is
no longer present, and a list of slot names of slots that were newly added
to the instance. Thus when a class is redefined:
(3) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, and the modification is propagated to subclasses. This is simpler
than (1) or (2).
The FOO example given above is implemented by defining a CLASS-REDEFINED
method that checks whether slot C is a new slot before initializing it.
The problem is that there can only be one CLASS-REDEFINED method, since
there is only one class object, so if the class is redefined multiple times
in ways that need CLASS-REDEFINED methods, this one method must contain
unmodular knowledge of all the redefinitions. In addition, in the
x-y-rho-theta example, if there are methods for accessing values that are
conceptually slots but are not physically represented as slots, the
CLASS-REDEFINED method has to know about the underlying slots used by
these methods, in case those slots have been deleted.
This "third way" seems simpler than the other two, so I hope that someone
can debug the problems mentioned in the previous paragraph. If not, we
need to make several changes mentioned here and there in this message in
order to make obsolete classes work.
∂27-Jul-87 0930 kempf%hplabsz@hplabs.HP.COM Re: Class Redefinition
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 09:29:49 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Mon, 27 Jul 87 09:28:47 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Mon, 27 Jul 87 09:28:24 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Mon, 27 Jul 87 09:26:23 pdt
Message-Id: <8707271526.AA11550@hplabsz.hpl.hp.com>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class Redefinition
In-Reply-To: Your message of 24 Jul 87 16:45:00 -0700.
Date: Mon, 27 Jul 87 09:26:20 -0700
From: kempf%hplabsz@hplabs.HP.COM
>
> (name-that-class new-class 'heh-heh)) ;Hm, what is this function
?
> I think we forgot to de> f> ine NAME-THAT-CLASS. It should be the thing such
> that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
Something like:
(setf (class-name new-class) 'heh-heh)
should work. The name is not listed as a slot in STANDARD-CLASS in the
87-003 metaobject protocol, however.
jak
------- End of Forwarded Message
∂27-Jul-87 0933 kempf%hplabsz@hplabs.HP.COM Technical corrections in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 09:32:43 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Mon, 27 Jul 87 09:31:19 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Mon, 27 Jul 87 09:30:46 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Mon, 27 Jul 87 07:45:32 pdt
Message-Id: <8707271445.AA11199@hplabsz.hpl.hp.com>
To: rpg@SAIL.STANFORD.EDU
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, olthoff@hplabsz.hpl.hp.com,
kempf@hplabsz.hpl.hp.com
Subject: Technical corrections in 87-002
X-Mailer: mh6.5
Date: Mon, 27 Jul 87 07:45:28 -0800
From: kempf%hplabsz@hplabs.HP.COM
Dick:
Apologies if this arrives more than once. Our mail system is
changing.
The formal specification of method application and combination
is completed, and a couple of omissions, typos, and other
technical errors were found. While I agree with Moon that it probably
isn't a good idea to inject a level of formalism into CLOS beyond that
customary for the Common Lisp community, I hope that the results of
work from those who are interested in such formalism can be fed back
into the design process, in the spirit of trying to make the CLOS
specification as precise as possible.
Here are the corrections:
1) The use of the term "partial order" on pg. 1-15, paragraph 1 implies
a relation on R which is reflexive, antisymmetric, and transitive. From the
text of the paragraph, this relation is presumably the "is a subclass of"
relation. However, earlier in the document, reflexivity is explicitly
excluded from the "is a subclass of" relation (pg. 1-4, paragraph 3),
since a class is defined to be neither a superclass nor a subclass
of itself. Either the partial order needs to be replaced
with a different order not requiring reflexivity (semiorder, etc.)
or the "is a subclass of" relation needs to be redefined
so that it is reflexive. Note that the latter solution is used in more
technical treatments of typing systems (e.g. Cardelli and Wegner, Computing
Surveys, 17, 1985, pp. 471-522).
2) As noted in the followup to my posting of the preliminary formal
specification for method applicaton and combination, the phrase "either
method may precede the other" on p. 1-21, last paragraph is not technically
correct, since the two methods are incomparable with regard to precedence. The
algorithm is nevertheless sound, because it describes sorting of method
equivalence classes rather than methods, and precedence between equivalence
classes, so the ordering of elements in a specific equivalence class is
arbitrary.
3) With reference to my original posting, the case of both specializers
being quoted objects cited on pg. 1-22, paragraph 3 cannot occur at that
point in the algorithm. Either one or the other can be a quoted object,
but since , by that point in the algorithm: a) the two methods
being compared must differ on the parameter specializer, and, b) in
order for a method to be applicable at all and the specializer to be
a quoted object, the specializer must be EQL to the parameter, this
condition cannot occur.
4) The formal description of class precedence list calculation on pg. 1-15,
paragraph 3 is lacking a condition. In the third line, it is not sufficient
just to require the existence of an index i, but also its minimality.
As a counterexample, consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4 c6)}
The inheritance graph for this is;
c5 c6
| |
c3 c4
| |
\ /
\ /
c2
|
c1
In the first step, cpl := [c1] and R := R\{(c1,c2)}, where A\B denotes
the set A with all elements of A INTERSECT B removed (quotient set).
Next step: cpl := [c1 c2] and R := {(c2,c3) (c2,c4)}. Now the set of
classes without predecessors is {c3 c4}. Then, according to the
description of the algorithm on pg. 1-15 paragraph 3, j=2 is the
largest number such that "there exists i=3 with c3 being the direct
superclass of c2," but i=4 also holds with this property, so it
cannot be determined whether c3 or c4 should be added to the class
precedence list. Requiring the minimal i to be used will remove
the ambiguity, in the example, making c3 the next element of the cpl.
I hope these corrections can be added to the next draft of the
CLOS document.
Jim Kempf kempf@hplabs.hp.com
∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Name That Class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:01:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 199633; Mon 27-Jul-87 12:53:29 EDT
Date: Mon, 27 Jul 87 12:53 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 19:45 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870727125306.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
I thought CLASS-NAMED was SETF'able, but 87-002 doesn't say so. Should
we change that?
∂27-Jul-87 1001 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Redefinition
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:01:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 199639; Mon 27-Jul-87 12:58:38 EDT
Date: Mon, 27 Jul 87 12:58 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 24 Jul 87 19:45 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870727125813.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
....
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
This doesn't conform to 87-002's specification that redefining a class
updates the existing class object, rather than replacing it with a new
class object. Indeed, if we changed that, we wouldn't need the concept
of "obsolete classes", as I pointed out in my message of early Saturday
morning (sent after you wrote this message, but before I saw your message;
we've had a lot of network problems lately, first with window-caulkers
parking their scaffolding in the middle of the through-the-air segment
of our network for a week, then MIT air conditioning failure, and who
knows what else.) However, because methods are classified by class
objects rather than class names, replacing the old class object with a
new one has its own complexities.
∂27-Jul-87 1046 Bobrow.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 27 Jul 87 10:46:17 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 27 JUL 87 10:46:00 PDT
Date: 27 Jul 87 10:45 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Name That Class
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 12:53 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
Message-ID: <870727-104600-1451@Xerox>
I thought CLASS-NAMED was SETF'able, but 87-002 doesn't say so.
Should we change that?
Yes.
danny
∂27-Jul-87 1159 RPG Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
(setf (class-named ...) ...) is good.
-rpg-
∂27-Jul-87 1224 RPG Class Redefinition
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon says: <your code won't work>.
I know that the specification states that my code won't work, but
many folks (and not unsophisticated ones) will think it should.
It would be nice if different classes weren't EQ. Is there no way to
make this work? Isn't it true that the only place we need to have
a class and its redefined class be the same is within method selection,
and can't we use surrogates there?
-rpg-
∂27-Jul-87 1700 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class Redefinition
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Jul 87 17:00:15 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ad05828; 27 Jul 87 17:02 EDT
Received: from ti-csl by RELAY.CS.NET id aw25936; 27 Jul 87 16:51 EDT
Received: from Jenner by tilde id AA12921; Mon, 27 Jul 87 09:16:28 CDT
Message-Id: <2763382458-15423174@Jenner>
Date: Mon, 27 Jul 87 09:14:18 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class Redefinition
In-Reply-To: Msg of 24 Jul 87 1645 PDT from Dick Gabriel <RPG@sail.stanford.edu>
Date: 24 Jul 87 1645 PDT
From: Dick Gabriel <RPG@sail.stanford.edu>
Subject: Class Redefinition
The problem with class redefinition is that the updating of instances can
be caused by arbitrary events, as far as the user is concerned. If none of
DEFCLASS, ADD-METHOD, MAKE-METHOD, CLASS-NAMED, the evaluation of the
special form FUNCTION, and garbage collection can update instances, then
if a CLOS implementation does not have multitasking, the following will
work (or something like it):
(let ((obsolete-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,(class-named 'heh-heh))
#'...)))
This code is not quite right, the new class object (produce by defclass
heh-heh is the same as the old one (the one you bound to
obsolete-class). [pg 1-11]
The following will work.
(let ((current-class (class-named 'heh-heh)))
(defclass heh-heh ...)
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,(get-obsolete-version current-class) ,current-class)
#'...)))
If there is a CLOS implementation with all of the properties named
above except it does have multitasking (including incremental GC),
then some form or macro like ATOMICALLY wrapped around the above
will work.
Right. However, the CPU time spent in ATOMICALLY can be quite
large, realistically some implementation will not be able to give an
upper bound for its elapsed time from start to completion. If a CLOS
implementation has to make sure that this time is kept short, it will
have to bear yet another constraint that could be avoided.
Something like this should work:
(let
((obsolete-class (class-named 'heh-heh))
(new-class (make-instance 'standard-class ...))) ;make an anonymous class
;that is the new HEH-HEH
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,new-class)
#'...))
(name-that-class new-class 'heh-heh)) ;Hm, what is this function?
This does not work for the same reason the first example did not work.
However I don't see how to fix this one without resorting to my
proposal. It would go like this:
(let*
((current-class (class-named 'heh-heh))
(obsolete-class (assoc current-class
(GET-OBSOLETE-CLASSES-FOR-REDEFINITION
current-class))))
(add-method
#'class-changed
(make-method ;later, make-instance
()
`(,obsolete-class ,current-class)
#'...))
(defclass heh-heh ...)) ;(name-that-class new-class 'heh-heh))
I think, though, that it probably makes sense to have Danny's version
of GET-OBSOLETE-CLASS for the same reason that I don't like UNIX - it's
too easy to do a DEFCLASS of an existing class and then wish you
had a handle on the old one. I think we need to decide whether Patrick's
versions of getting obsolete classes are worth having around to simplify
life.
If you can find another solution to your second example (ie without
using ATOMICALLY), I would be inclined to live with Danny's
proposal.
I think we forgot to define NAME-THAT-CLASS. It should be the thing such
that MAKE-INSTANCE + (<the thing> <name>) = (DEFCLASS NAME ...).
This thing will be in the metaclass protocol
Patrick.
∂27-Jul-87 1905 Moon@STONY-BROOK.SCRC.Symbolics.COM initialization meeting notes
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 19:05:41 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 200139; Mon 27-Jul-87 22:06:01 EDT
Date: Mon, 27 Jul 87 22:05 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: initialization meeting notes
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870723180901.2.GREGOR@SPIFF.isl.parc.xerox.com>
Message-ID: <870727220545.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 23 Jul 87 18:09 PDT
From: Gregor.pa@Xerox.COM
In this message I try to summarize what we agreed at the meeting in
Boston.
Thanks for getting all this on-line. I see only two things to disagree
with here, so we should start putting our heads down and agreeing on the
next level of detail.
(defmethod initialize-instance ((obj object) &rest initargs)
;; The default initialize-instance method deals with setting the
;; values of slots from slot-filling-initargs and from initforms.
;;
;; The rules are that the leftmost initarg which is declared
;; as setting a slot (with the :initarg slot option) actually
;; does set it (or is it the rightmost?); and that slots which
;; are not set by an initarg have their :initform evaluated and
;; used to set them.
)
It's leftmost, because that's the way duplicated &key arguments work
in all other Common Lisp functions.
Actually there are two issues here:
(1) If the same initarg appears more than once in the initargs list,
the leftmost occurrence is used and later occurrences are ignored.
This is just consistency with &key and there's really no choice.
(2) If more than one initarg is defined to fill a given slot, and more
than one of these initargs appears in the initargs list, what happens?
Flavors takes the rightmost, but that's a misfeature. We should either
signal an error or take the leftmost. It's a one-line change to make
Flavors take the leftmost (it will be a few microseconds slower, due to
doing MEMBER of a one-element list instead of EQ, not enough slowdown
to matter). I like taking the leftmost better than signalling an error.
(defclass ship ()
((x :initarg :x)
(y :initarg :y)))
(defmethod initialize-instance :after ((s ship) &key startp)
(when startp (start s)))
(defmethod start ((s ship))
(with-slots ((s :use-accesors nil))
(if (AND X Y)
<start it up>
(error "Have to set X and Y before starting a ship."))))
(One line of the above has been uppercased, the only ASCII way to
highlight it.)
I hope this is an erroneous example, and you're not really proposing that
otherwise-uninitialized slots should be initialized to NIL.
the only serious problem has to do with arranging for the default
initarg value forms to be evaluated in the lexical environment of the
defclass. (Of course if environments were first class objects this would
be trivial...)
I thought we agreed that defclass would translate the initforms into
functions and at the metaclass level they would appear as functions. I
don't think we need a new way, besides lambda, for capturing lexical
environments. (Of course implementations are not required to make new
functions in all cases; especially in the case of constant initforms,
they will probably make a closure of an existing function.) This implies
that one cannot use metaclass protocol to recover the original forms
that appeared in the defclass. Maybe we didn't agree on this, I couldn't
find anything about it in my notes from the meeting. Can we converge
on this now?
∂27-Jul-87 2012 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 27 Jul 87 20:12:22 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 200153; Mon 27-Jul-87 22:46:48 EDT
Date: Mon, 27 Jul 87 22:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July. The rest of this
message is it.
This page is things that I think we agreed that we had decided
after the March meeting and before the July meeting.
27 May 87 call-next-method is allowed to take arguments, however it is
an error to give it arguments that would change the set of applicable
methods. I think we're saying this signals an error, and mentioning
that in some simple cases the lack of need for an error check can be
proved at compile time, but in general a run-time check is required.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
!
This page is a list of issues on which we should make decisions,
brought up by Danny. Where I saw responsive answers in the mail
(there were very few) I have edited them in. I've removed comments
that were purely editorial comments on the document.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, I think
because existing interfaces might not be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this.
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
In July we decided to defer this.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function.
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
We need to decide whether class-name of an anonymous class is nil.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
Kempf agrees they should return the object. Moon isn't sure, because
defun, defvar, deftype, and defstruct return the name. As far as I can
tell every defxxx form in CLtL returns the name. The problem is that
we haven't admitted that defmethod has a name.
In July we decided (for the previous three) to return the object for
all CLOS defxxx functions (being inconsistent with Common Lisp).
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. Then we said we'd discuss it further in the mail.
I think we agreed that the turning of two setf argument lists into one should
depend only on the argument lists, and not on the generic function object.
[My notes include an illegible comment, I think it means that I still hope
we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one.]
p2-39 Arguments: "list of t's" should be replaced by "list of classes
named t" since get-method only takes specializers, not names of
specializers.
Agreed.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
p2-51 print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
Gregor will propose the details.
!
This page is a list I made in March, keyed by page numbers in the
document, that hasn't been shown to anyone yet. Issues mentioned
earlier, or that have since died, have been removed. I've removed
comments that were purely editorial comments on the document.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means.
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
2-13 class-named needs a new name for consistency. get-class would be wrong
because the other get-xxx functions aren't name operations. symbol-class
is the agreed name. It needs an environment argument. The errorp argument
gets in the way. I think we agree that symbol-class should be setf'able,
but can it only be set once for a given symbol or is it allowed to change
the symbol-to-class-object mapping?
2-16 (slot-name form) should be allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
but it never finds its way into the document.
In July we rejected this. Since people keep assuming it, we have
to document explicitly that it is not allowed.
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-40 get-setf-generic-function needs an errorp, but it and ensure-generic-function
should be subsumed by get-generic-function which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Gregor promised to mail out the proposal.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
!
Documented holes in chapters 1 and 2 of 87-002. We publicly promised
X3J13 that we would finish these and have a new draft of 87-003 by the
next meeting.
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
!
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Ida: make-specializable seems to be missing
Gregor's proposal for get-generic-function will subsume this.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
Should we just flush multiple-value-prog2, as leading to more discussion
than is warranted by its simplification of the presentation of
define-method-combination?
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
Should we flush defmethod-setf and friends in favor of function specs?
It probably turns out they could be just in the macros and not in the
underlying Lisp. The big issue is standardizing where the "new-value"
argument goes; but we may do that anyway (mentioned earlier in this file).
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe?
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
The fact that symbol-function (the user callable primitive) needs to
be split from the subprimitive for implementators that gets and sets
the "real" function definition of a symbol. This is so when a symbol's
function definition is a generic function object, the "real" definition
can be something that is easier for the implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gergor volunteered to send some mail about this.
Clarify that because class names and classes are type-specifiers, they can be
validly be used in THE special forms and in TYPE declarations. We forgot this
when we clarified that class objects can be used with TYPEP and SUBTYPEP.
July: agreed
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
Need to be able to get at the obsolete classes associated with a class,
to put methods on them.
Patrick has proposed.
Need discussion of how instances are transformed one step at a time
when a class has been redefined multiple times.
∂28-Jul-87 1447 Bobrow.pa@Xerox.COM Re: Category Errors
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 14:46:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 14:46:54 PDT
Date: 28 Jul 87 14:46 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Category Errors
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 24 Jul 87
14:59 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-144654-2241@Xerox>
Here is a generic function ``in CLOS'':
Add-method generic-function method
And here is how we have ``carefully laid out ... the range of
legal arguments'' to it:
Arguments:
The generic-function argument is a generic function object.
The method argument is a method object. The lambda-list of
the method function must be congruent with the lambda-lists of any
other methods associated with the generic function and with the
lambda-list of the generic function.
(page 2-5, FUNCTIONS)
We should have been more careful about our wording perhaps. Because we
have not yet formalized the notion of protocol, we have had to say the
the first argument is a generic-function. But it could of course be any
object that satisfied the same protocol (could act as the argument to
some set of generic-functions). It is the ability to specialize (make
"is a generic-function object" mean "be an instance of a subclass of
generic-function object") and the ability to create alternative
implementations that is one of the important improvements that object
oriented programming adds to Lisp -- Hence a MAJOR feature. Users who
ask "what's that thing?" have not understood object oriented
programming, and it is up to us to help explain it -- not apologize for
it.
∂28-Jul-87 1527 Bobrow.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 15:26:54 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 15:26:43 PDT
Date: 28 Jul 87 15:26 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Class Redefinition
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jul 87
12:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-152643-2322@Xerox>
rpg says
It would be nice if different classes weren't EQ. Is there no
way to make this work?
The problem is what is a different class. People build networks of
objects, including classes. The point of the spec is that these
networks (including the one in the class lattice) should have to change
when a class is changed. People do not always refer to classes by
names.
Response to Moon:
Although I have not thought about it a lot, I think Moon's refinements
GET-CLASS-FOR-NEXT-REDEFINITION
and
GET-OBSOLETE-CLASSES
seems fine. I don't understand the experience of why one gets into
trouble making CLASS-CHANGED methods after redefinition as Moon says,
but perhaps it is because I am not working in a true multi-process
system.
I think we have only two choices with respect to methods applicable to
obsolete instances--
1) All methods applicable to the class itself i.e. the obsolete-class is
a subclass of the new class
2) Only slot-value-using class.
A problem with the first is what happens if a method is removed from a
class before an obsolete instance is converted to a real instance. For
example, in the famous rho-theta example, suppose we have x-y points
(ones with x and y as slots), and decide to change class to store only
rho and theta. Then after redefining the class, a naive user might
1) build a class-changed method that used the methods for rho and theta
for conversion
2) believe that these rho and theta methods could be removed from the
rho-theta-point class.
In this description I have made it obvious why this is wrong. But
suppose this were a case where both of generic functions for rho and
theta used another routine that was no longer needed. The user might
easily delete that one.
I think that it might be better to go to 2, though clearly it makes
class-changed have a lot less easily accessible power.
∂28-Jul-87 1550 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 28 Jul 87 15:49:56 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa18740; 28 Jul 87 18:40 EDT
Received: from ti-csl by RELAY.CS.NET id aa01279; 28 Jul 87 18:30 EDT
Received: from Jenner by tilde id AA20926; Tue, 28 Jul 87 15:53:07 CDT
Message-Id: <2763492729-5527834@Jenner>
Date: Tue, 28 Jul 87 15:52:09 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Class redefinition and class-changed.
In-Reply-To: Msg of Sat, 25 Jul 87 01:26 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
I don't like Patrick's particular proposal, though.
GET-OBSOLETE-CLASSES-FOR-REDEFINITION is too complicated, because it
returns a whole alist rather than being just the primitive. In addition, I
don't think the set of "classes implicated in the class-redefinition of
CLASS" is computable until the details of the redefinition are known.
Suppose
(defclass one () (a b))
(defclass two (one) (c))
(defclass three (one) (d))
Now suppose we redefine one as follows:
(defclass one () (a b d))
Referring to the third paragraph on page 1-11 of 87-002, one and two are
"implicated", but three is not, or at least, whether three is implicated is
implementation-dependent. But if the new slot had been named e, both two
and three would have been implicated. I don't think the information in
Patrick's alist is needed anyway; when defining a method, one only defines
it for the obsolete class corresponding to one class. If a different
method needs to be defined for an obsolete subclass, the function can be
called again.
I see. I don't care that much about the alist as long as we can get the
obsolete class of "one".
Thus I would replace Patrick's proposal with GET-OBSOLETE-CLASS-FOR-REDEFINITION
which takes one argument, a class, and returns one value, the obsolete class
that is a copy of the current definition of the class and will be used the next
time the class is redefined; this is created the first time you ask for it.
Perhaps GET-OBSOLETE-CLASS-FOR-NEXT-REDEFINITION would be a better name.
As Danny proposed, a primitive to get the obsolete classes corresponding to
redefinitions that have already taken place is useful, for instance in case
you didn't realize ahead of time that you would need a CLASS-CHANGED method
and now want to patch up the program. I would suggest a function
GET-OBSOLETE-CLASSES-FOR-PAST-REDEFINITIONS which takes one argument, a
class, and returns one value, a list of obsolete classes, newest first.
Sounds OK.
I'll have to think some more about the rest of the message. Our
connection with Arpanet was broken and we got it back just one
hour ago.
Patrick.
∂28-Jul-87 1642 Gregor.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 16:42:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 16:42:34 PDT
Date: 28 Jul 87 16:42 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Class Redefinition
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 28 Jul 87 15:26 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-164234-1120@Xerox>
The need for get-class-for-next-redefinition doesn't really have
anything to do with multi-processing as far as I can see. Suppose that
(the class of) one of the objects actually involved in defining a method
on class-changed was going to be rendered obsolete by a certain defclass
form. In that case, you would need to define the method before you
actually change the class definition.
∂28-Jul-87 1648 Gregor.pa@Xerox.COM Re: Class Redefinition
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 16:48:48 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 16:48:45 PDT
Date: 28 Jul 87 16:48 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Class Redefinition
In-reply-to: Danny Bobrow <Bobrow.pa>'s message of 28 Jul 87 15:26 PDT
To: Bobrow.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-164845-1137@Xerox>
As far as "it would be nice if different classes weren't EQ" goes.
Stop thinking about names and naming! If you do, I think it becomes
easier to see why the obsolete class should be a new object and the old
class object should be updated to have the new definition.
defclass just associates a class with a name for convenience. Many
programs will use anonymous classes. In these programs, changes in an
anymous or a named class might cause anymous or named classes to become
obsolete. The obsolete class mechanism needs to support both anonymous
and named classes. In order to do that, the 'redirection' needs to be
at the level of the class object not at the level of the class name.
∂28-Jul-87 1751 Bobrow.pa@Xerox.COM Re: initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 17:51:25 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 17:51:21 PDT
Date: 28 Jul 87 17:51 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: initialization meeting notes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 22:05 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870728-175121-1220@Xerox>
This implies that one cannot use metaclass protocol to recover
the original forms that appeared in the defclass.
This seems an unecssary mistake (we could have redundant information at
the very least). I agree that we need not have any "new way, besides
lambda, for capturing lexical
environments."
∂28-Jul-87 1907 Gregor.pa@Xerox.COM Re: initialization meeting notes
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 19:07:26 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 19:04:56 PDT
Date: 28 Jul 87 19:04 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: initialization meeting notes
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 27 Jul 87 22:05 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870728-190456-1292@Xerox>
From: Moon
(One line of the above has been uppercased, the only ASCII way
to highlight it.)
I hope this is an erroneous example, and you're not really
proposing that otherwise-uninitialized slots should be initialized
to NIL.
Yes, this example is erroneous. What I was trying to capture was that
an :after initialize-instance method would be able to tell if a slot had
been set.
I thought we agreed that defclass would translate the initforms
into functions and at the metaclass level they would appear as
functions. I don't think we need a new way, besides lambda, for
capturing lexical environments. (Of course implementations are not
required to make new functions in all cases; especially in the case
of constant initforms, they will probably make a closure of an
existing function.) This implies that one cannot use metaclass
protocol to recover the original forms that appeared in the
defclass. Maybe we didn't agree on this, I couldn't find anything
about it in my notes from the meeting. Can we converge on this now?
I remember now that we had agreed that both initforms and default
initargs would be translated into functions by defclass. Note that this
does not necessarily mean that its impossible to reconstruct the
defclass form for a class. We could say that at the metaclass level,
there is a separate mechanism for communicating the form that was in the
defclass.
But I would just as soon agree that there is no such mechanism at the
metaclass level. Actually, I think the fact that Common Lisp doesn't
have first class lexical environments means that its impossible to
construct an 'equivalent' defclass form which an editor might put up for
the user to edit a little and then re-evaluate. Only specific
implementations, in an implementation specific way will be able to do
this.
On the other hand, if Common Lisp had first class lexical environments,
this would be easy. An unemployment would be lower. And the national
debt would be under control, and glphh... uh...
∂28-Jul-87 1922 Gregor.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 28 Jul 87 19:22:30 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 28 JUL 87 19:21:57 PDT
Date: 28 Jul 87 19:21 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Name That Class
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 27 Jul 87
11:59 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870728-192157-1316@Xerox>
It seems to me that there are ways for class-named and setf of such to
work. I think only two of these are reasonable, but I will include the
third for completeness. Note that this same analysis applies to
generic-function-name and setf of symbol-function and
get-setf-generic-function. I will do class names first.
A class C 'is bound to' a given name Ni iff (class-named Ni) returns C.
In all this solutions, we document class-named and setf of class-named.
We say that class-named returns the class is bound to a particular name.
We say that setf of class-named can be used to set the binding of a
class to a name.
Solution 1:
Only document class-named and setf of class-named. Most
implementations will have some magic for printing out a class's name
when it has one.
Solution 2:
Document class-named and setf of class-named. Also document
class-name, but say that the the class may or may not 'bound' to that
name.
Solution 3:
Document class-named and class-names and setf of class-named. Say
that setf of class-named can be used to bind a clas to a name. Say that
class-names returns the list of all names that a class is bound to. For
example:
(setq foo (make-instance 'standard-class))
#<Standard-Class NIL 1>
(setf (class-named 'n1) foo)
#<Standard-Class N1 1>
(setf (class-named 'n2) foo)
#<Standard-Class N2 1>
(class-names foo)
(N1 N2)
(setf (class-named 'n1) nil)
#<Standard-Class N2 1>
(setf (class-named 'n2) nil)
#<Standard-Class NIL 1>
(class-names foo)
()
It seems to me that solution 1 and solution 3 are the only reasonable
ones. My general dislike of names makes me prefer solution 1, but I
think that solution 3 actually provides users some important
functionality.
I think its easy to see how this whole thing would work for
generic-function-name, symbol-function, setf of symbol-function,
get-setf-generic-function and setf of get-setf-generic-function.
∂28-Jul-87 2126 RPG Partial Orderings
To: common-lisp-object-system@SAIL.STANFORD.EDU
You can define a partial ordering based on irreflexive relations
by using the `antirelation' and NOT. For example, instead of less than
or equal, you can use greater than and NOT. If you don't believe me,
believe Knuth Volume 1.
-rpg-
∂29-Jul-87 1025 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Miscellaneous decisions taken or to be taken
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Jul 87 10:25:11 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ac27103; 29 Jul 87 13:10 EDT
Received: from ti-csl by RELAY.CS.NET id af06356; 29 Jul 87 13:02 EDT
Received: from Jenner by tilde id AA12158; Wed, 29 Jul 87 11:22:06 CDT
Message-Id: <2763562862-9741514@Jenner>
Date: Wed, 29 Jul 87 11:21:02 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Msg of Mon, 27 Jul 87 22:46 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
I agree with it.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, I think
because existing interfaces might not be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this.
I agree with Gregor.
∂29-Jul-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM updated documentation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 29 Jul 87 10:34:40 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 201218; Wed 29-Jul-87 13:27:29 EDT
Date: Wed, 29 Jul 87 13:26 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: updated documentation
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870729132641.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
I wrote new versions of the functions, concepts, and design chapters.
The documentation now includes the write-up about Standard Type Classes
which I sent to this list several months ago. I didn't receive any
comments about it, probably because the text was cluttered up with tex
formatting directives. When we format the document again it will be
easier for people to read this section and make their comments then.
I changed the documentation to state that the def-XXX macros return
objects, not names. We agreed on this change at our Cambridge meeting
a couple weeks ago.
The only problem with this is some awkwardness about the value of
define-method-combination. There is no CLOS object for representing a
method combination type. define-method-combination expands into a
defmethod, so its result is a method object.
∂29-Jul-87 1415 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Class redefinition and class-changed.
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 29 Jul 87 14:15:18 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae29814; 29 Jul 87 17:07 EDT
Received: from ti-csl by RELAY.CS.NET id ae07913; 29 Jul 87 17:02 EDT
Received: from dsg by tilde id AA02476; Wed, 29 Jul 87 15:11:11 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Wed, 29 Jul 87 15:00:19 CDT
Message-Id: <2763575892-10524347@Jenner>
Date: Wed, 29 Jul 87 14:58:12 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Class redefinition and class-changed.
In-Reply-To: Msg of Sat, 25 Jul 87 01:26 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
We have our choice of three ways to define what happens when a class is
redefined:
(1) A new class object is created, the name-to-class-object mapping is
changed, defclass-defined methods implied by the new definition are put on
the new class object, all methods other than defclass-defined methods that
apply to the old class are made to apply also to the new class, subclasses
of the old class are made to be subclasses of the new class instead, and
superclasses of the old class are made to be also superclasses of the new
class. If we had done this, there would have been an explicit
representation of versions of a class, and there would not have been any
concept of "obsolete classes."
I don't like this one for the reasons Gregor and Danny gave.
This means that -both- arguments to CLASS-CHANGED could be instances of
obsolete classes. It also means that our CLASS-CHANGED method can't
specialize its second parameter, because at first that will be the class
FOO, but after FOO is redefined again, it will be an obsolete class. If we
don't specialize the second parameter, it seems we could be confused by
CLASS-CHANGED being called when CHANGE-CLASS was used to change an instance
of FOO into an instance of BAR. This is not a problem if CHANGE-CLASS,
like all other generic functions, first updates its argument to the latest
definition of its class, before changing it to the new class; then a method
specialized to an obsolete class in its first parameter can never be called
with the second parameter an instance of anything other than the next newer
version of the same class. This all seems slightly kludgey, but does seem
like it should work.
I like this approach the best because it is more object oriented than
the third one and seems more modular. However it has the problem Danny
mentioned about applicable methods:
[Bobrow]:
I think we have only two choices with respect to methods applicable to
obsolete instances--
1) All methods applicable to the class itself i.e. the obsolete-class is
a subclass of the new class
2) Only slot-value-using class.
A problem with the first is what happens if a method is removed from a
class before an obsolete instance is converted to a real instance. For
example, in the famous rho-theta example, suppose we have x-y points
(ones with x and y as slots), and decide to change class to store only
rho and theta. Then after redefining the class, a naive user might
1) build a class-changed method that used the methods for rho and theta
for conversion
2) believe that these rho and theta methods could be removed from the
rho-theta-point class.
In this description I have made it obvious why this is wrong. But
suppose this were a case where both of generic functions for rho and
theta used another routine that was no longer needed. The user might
easily delete that one.
I think that it might be better to go to 2, though clearly it makes
class-changed have a lot less easily accessible power.
I don't like danny's 1) because as he shows, it does not work. I don't
like 2) because it breaks modularity. You have to know if an accessor
is implemented as a physical slot access and if not, you have to know
what the accessor was doing. This knowledge is contained in your class
and its superclasses.
How about this one?
1b)All methods applicable to the class itself at the time of the
redefinition.
It would be up to the implementation to choose the best way of doing
it.
The third way to define what happens when a class is redefined, mentioned
earlier, is as follows: Don't try to use CLASS-CHANGED for both changing
the class of an instance and updating an instance to a new version of its
class. Invent a new generic function CLASS-REDEFINED, which is called when
an instance is updated to a new version of its class. This avoids the
complicated concept of "obsolete classes", at the cost of conveying the
former state of the instance in a less object-oriented fashion. Perhaps
CLASS-REDEFINED would receive three arguments: an instance of the class,
already updated to the latest definition of the class, a property list
associating slot names to slot values, with one entry for each slot that is
no longer present, and a list of slot names of slots that were newly added
to the instance. Thus when a class is redefined:
(3) The old class object is modified, defclass-created methods that aren't
created by the new defclass are removed, new defclass-created methods are
added, and the modification is propagated to subclasses. This is simpler
than (1) or (2).
The third way is simpler indeed. My main objection to this is that
CLASS-REDEFINED methods have to know all about the implementation of the
class and superclasses (physical slots and methods) AND the whole story
about the successive redefinitions.
Patrick.
∂30-Jul-87 0021 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 30 Jul 87 00:20:49 PDT
Received: from hplms1 by hplabs.HP.COM with TCP ; Wed, 29 Jul 87 15:26:18 pdt
Received: from hplabsz.hpl.hp.com by hplms1; Wed, 29 Jul 87 15:24:58 pdt
Return-Path: <kempf@hplabsz.hpl.hp.com>
Received: by hplabsz; Wed, 29 Jul 87 16:25:29 pdt
Message-Id: <8707292225.AA09896@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, kempf@hplabsz.hpl.hp.com
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Your message of Mon, 27 Jul 87 22:46:00 -0400.
<870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 29 Jul 87 16:25:25 -0700
From: kempf%hplabsz@hplabs.HP.COM
On anything not noted, I've got no opinion.
There was no mention made of compile time optimization, which I believe
I made some initial proposals on in late April or early May. I've been
meaning to revist them, will try to get to that in the next week or
so. If anybody thinks this isn't important and should be dropped, let
me know. Our applications developers are asking for it, however.
On initialization:
> 1-5, 2-44 The initialization protocol for make-instance is not yet
> specified.
I take it there was no agreement at the July meeting to a full specification?
If so, then can someone write up the specification and post it?
PART I:
> 27 May 87 call-next-method is allowed to take arguments, however it is
> an error to give it arguments that would change the set of applicable
> methods. I think we're saying this signals an error, and mentioning
> that in some simple cases the lack of need for an error check can be
> proved at compile time, but in general a run-time check is required.
This is fine. Do we need to further clarify the error based on Dick's
note about error signaling?
> 10 June 87 There was no response when Sonya mailed out a writeup for how
> the standard type classes are organized. Does that mean we agreed on that?
Yes, modulo consideration of Patrick's suggested change in
<2762944528-5369042@Jenner> for purposes of minimizing category errors.
But I assume from the note he posted today, that he is satisfied with
Sonya's note.
> p1-12 Should defclass be allowed to change the metaclass of an existing
> class? Under what conditions should a subclass of standard-class have
> the same properties wrt instance updating as standard class?
> Kempf says you shouldn't be allowed to change the metaclass, I think
> because existing interfaces might not be transformable.
> Gregor says the metaclass protocol includes a predicate function
> that controls this.
The reason was because the representations might differ. Consider a
metaclass where the types of the slots were restricted. Instances of
classes of a metaclass which did not have those restrictions might be
difficult to update automatically. However, I think Gregor's solution of
a metaclass protocol predicate (generic) function to control this would
be sufficient.
This doesn't answer the second question, however, I'll abstain on that
one. I don't believe instance updating belongs in the language in the
first place, but rather in the environment.
PART II:
> p1-17 "It is currently under discussion whether to provide constructs
> for giving generic functions local names." Do we want to have this
> discussion, or to punt on this syntax. I recall we did come up with some
> reasonble semantics for a GFLET and GFLABELS.
>
> In July we decided to defer this.
Let's forget it for now. I've got some ideas, but I won't rehash them.
> p1-18 It is not specified whether get-setf-generic-function is a
> setf-able form. I suggest that it be made so. This would allow one to
> trace setf-generic-function's without having to know their names.
> This set off a discussion of how TRACE should work that maybe doesn't
> bear directly on CLOS.
> Moon thinks this would be okay provided it is understood as setting the
> mapping from a name to a generic function, not side-effecting the
> generic function.
I've been thinking about modifications to TRACE to support tracing of
generic functions, which combines aspects of Danny's idea of making
TRACE a generic function and Moon's function specs. I'll try to get
it written up and posted by the end of the week. I think it's important
that this be addressed, since our applications developers are beginning
to express the need for the ability to trace individual methods, as
well as invocation of the generic function.
> p1-24 Should we have a call-next-method? which calls such a next method
> if it exists, else returns nil (rather than signalling an error?). This
> seems useful rather than having to define many base methods on object.
CommonObjects had two messaging forms for this, but my general inclination
is to conform with what happens when an attempt to invoke a generic
function is made with an argument set for which there is no matching
method. Currently, an error is signalled, and I think that it should
also be for CALL-NEXT-METHOD.
> We need to decide whether class-name of an anonymous class is nil.
Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
second. An anonymous class should be a class with NO name.
> p2-19 Values: I thought we agreed that all top level forms should return
> the object. It says here defclass "returns the name of the class"
> p2-22 Same comment as 2-19, for defgeneric-options
> 2-24 ditto for defgeneric-options-setf
> Kempf agrees they should return the object. Moon isn't sure, because
> defun, defvar, deftype, and defstruct return the name. As far as I can
> tell every defxxx form in CLtL returns the name. The problem is that
> we haven't admitted that defmethod has a name.
> In July we decided (for the previous three) to return the object for
> all CLOS defxxx functions (being inconsistent with Common Lisp).
Additionally, it would be nice if
top level forms would also print out something at compile time. Our
applications developers are asking for some feedback about what gets
done at compile time. Maybe that's an implementation issue, though.
> p2-35 The argument order of the setf method ought to be documented here.
> Gregor proposed that new-value be the first argument. Any problem with
> this?
> Kempf doesn't care but his users want it to be the second argument.
> Moon doesn't care but his users are used to it being the last argument.
> In July we suggested making the new-value argument a required argument that
> comes after all the other required arguments, and before the optional, rest
> and keyword arguments. Then we said we'd discuss it further in the mail.
> I think we agreed that the turning of two setf argument lists into one
> should
> depend only on the argument lists, and not on the gen eric function object.
> [My notes include an illegible comment, I think it means that I still hope
> we can keep things abstract enough that we don't have to document
> how the two setf argument lists are turned into one.]
This sounds good to me.
> p2-39 Arguments: "list of t's" should be replaced by "list of classes
> named t" since get-method only takes specializers, not names of
> specializers.
Yes, except I'd phrase it as "a list whose elements are the class object
for the the class named T". As I understand it, there is only one class T.
> p2-51 print-object should take a depth argument.
> Moon strongly disagrees and points to the fourth bullet. I believe this
> issue was discussed to death on the Common Lisp mailing list a few months
> or a year ago.
> The point is that every single method for print-object should not have to
> deal with *print-level*; that's unmodular.
> Kempf raised a consistency argument (with defstruct?) but we decided
> not to change print-object.
I agree with Moon. Some implementors may scream (as I did),
but it's probably not too late to correct this blemish.
PART III:
> 2-6 call-next-method dynamic versus indefinite extent
> The document says it has dynamic extent; we need to be sure that we
> really mean that. In July we said "implementation flexibility, not
> really a language thing", but I'm damned if I can figure out what
> that means.
Yes, this needs to be resolved. See my comments below about adding
methods to more than one generic function. Although I wasn't there,
I think the "implementation flexibility" comment had something to
do with optimizing calculation of the effective method. Indefinite
extent would favor this, but dynamic extent would give more flexibility
with regard to what could be done with method objects. Indefinite
extent sounds good to me, but I'm not particularly choosy, however,
I think it should be pinned down.
> 2-9 semantic difficulties discussion was shortened for the document so much
> that much of the point was lost. At some point we need to decide how much
> we want to standardize about this and where we want to say it; in the main
> standard or in some kind of implementation guide.
I think these semantic difficulties point out a fundamental problem with
CHANGE-CLASS. It is neither a full versioned class capability nor an
environmental undo capability, but rather a hack somewhere in between. Having
said my peace (and above, about instance changing), I'll forgoe any
further comments.
> 2-13 class-named needs a new name for consistency. get-class would be wrong
> because the other get-xxx functions aren't name operations. symbol-class
> is the agreed name. It needs an environment argument. The errorp argument
> gets in the way. I think we agree that symbol-class should be setf'able,
> but can it only be set once for a given symbol or is it allowed to change
> the symbol-to-class-object mapping?
Why an environment argument? Since we haven't agreed to lexically scoped
class names, this would seem unnecessary. Is it to deal with the ERRORP
argument? Why do people think it will get in the way? Why not just make
it a keyword argument? A user might want to not have it signal an error
especially in metaclass programming. If whether or not it signals an
error is dependent on a (second-class) environment argument, then it
will be more difficult for a user to arrange. I think the name SYMBOL-CLASS
is OK, and that it should be allowed to change the
symbol-to-class-object mapping.
The important thing in CLOS is the object, and the name to object mapping
should be changable.
> 2-16 (slot-name form) should be allowed as an abbreviation
> for (slot-name :initform form). People have been assuming this,
> but it never finds its way into the document.
> In July we rejected this. Since people keep assuming it, we have
> to document explicitly that it is not allowed.
Yes.
> 2-16 boa-arglist should support &key and &allow-other-keys.
Agreed.
> 2-19 uninitialized slots should be an error to reference, not be defined
> to return an unstandardized value with no error. I'm willing not to require
> that it signals an error if people feel that would be an undue burden,
> otherwise I prefer that reading an uninitialized slot signals an error.
I agree that it should signal an error.
> In July we decided that signalling an error here should depend on the
> declared safety level. Dick has proposed terminology for this.
Dick's terminology is good. We probably need to backpatch it into the
document (it should probably be backpatched into CLtL too, but that's
not for us to decide).
> 2-57 with-slots :prefix package problem; This was discussed in the mail and
> then the ball was dropped. What's in the document is unworkable because it
> depends on the dynamic value of *package* at macro-expansion time, but Common
> Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
> prefer to flush the :prefix option. An alternative
> that was discussed was to
> use symbol-package of the prefix, both here and in defclass accessor construc-
tion,
> as the package, relying on the likelyhood of prefixes always ending in delimi-
ter
> characters and exported symbols never ending in delimiter characters.
> July: We agreed to resolve this in the mail.
I agree with Moon.
> 2-57 What does with-slots do for slots that exist in the class but don't
> have accessors, when :use-accessors t is specified (or defaulted)?
> July: it shadows any outer bindings of the slot name, and if you
> actually access that pseudo-variable, it signals an error.
Agreed.
> Documented holes in chapters 1 and 2 of 87-002. We publicly promised
> X3J13 that we would finish these and have a new draft of 87-003 by the
> next meeting.
See my note of 27 July to Dick about holes in Chapter 1. I'll be replying
to Danny's comments on it shortly.
> 1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
> is still under discussion.
Has a Cleanup Committee proposal been submitted for the type system?
> What can be done with method objects, e.g. can one method be added
> to more than one generic function?
There may be a problem if the method invokes CALL-NEXT-METHOD. This
relates back to whether CALL-NEXT-METHOD is dynamic or indefinite
in extent. If it is dynamic, then there should be no problem, since
the binding of CALL-NEXT-METHOD is done when the method begins executing,
at the latest, or during calculation of the effective method, at the
earliest. Thus the same method object on multiple generic functions
would be no problem, since that case could be detected and establishment
of CALL-NEXT-METHOD's binding deferred as late as possible. If the
extent is indefinite, then the binding could potentially remain outside
of a particular method invocation, and so adding the same method to
more than one generic function may cause a problem.
> Ida: make-specializable seems to be missing
> Gregor's proposal for get-generic-function will subsume this.
Wasn't ENSURE-GENERIC-FUNCTION supposed to replace this?
> Should we just flush multiple-value-prog2, as leading to more discussion
> than is warranted by its simplification of the presentation of
> define-method-combination?
Yes.
> Which symbols defined by the standard go in what package?
> July: I think we said some will go in LISP: and some will go in CLOS: and
> we don't know yet where to draw the line.
I think they should all go into CLOS, except those which are already in
LISP (like DOCUMENTATION) or those which are designed to replace aspects
of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
> Should we flush defmethod-setf and friends in favor of function specs?
> It probably turns out they could be just in the macros and not in the
> underlying Lisp. The big issue is standardizing where the "new-value"
> argument goes; but we may do that anyway (mentioned earlier in this file).
I think we ought to keep DEFMETHOD-SETF, but use function specs (or
something like them) as the programmer interface to TRACE. See my
comments above about TRACE.
> Should we adopt the :component-order class-option from Flavors, as a
> simple way for the user to have control of the CPL without making him
> write his own algorithm?
> Gregor doesn't like the ability to specify constraints on the ordering
> of classes that only apply conditionally, i.e. if those classes are
> actually present among the superclasses. He considers this bad style.
> Moon volunteered to write a proposal with some examples, and we agreed
> to resolve this over the mail.
I agree with Gregor. I think that user specified changes in the CPL
should be controlled through COMPUTE-CLASS-PRECEDENCE-LIST, or, if
the default algorithm can't make a decision.
> The fact that symbol-function (the user callable primitive) needs to
> be split from the subprimitive for implementators that gets and sets
> the "real" function definition of a symbol. This is so when a symbol's
> function definition is a generic function object, the "real" definition
> can be something that is easier for the implementation to call.
I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations. Currently, most of the
PCL-derived implementations have no trouble with this.
> July: We need to say explicitly somewhere that calling symbol-function
> of the name of a generic function is required to return the generic
> function object, not the "real" definition.
Yes.
> I'm not sure if we said anywhere what happens when you call a generic
> function and there is no applicable method; I think it ought to signal
> an error.
Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
in the context of Dick's proposed error naming scheme.
> Clarify that because class names and classes are type-specifiers, they can be
> validly be used in THE special forms and in TYPE declarations. We forgot this
> when we clarified that class objects can be used with TYPEP and SUBTYPEP.
> July: agreed
Yes. Again, as mentioned in the beginning, this relates back to compile
time optimization.
> funcallable-standard-class should be documented. It is a metaclass.
> This is what makes generic function objects funcallable. There is a slot
> that is the actual function that gets called.
Agreed.
∂30-Jul-87 0612 DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET Re: Miscellaneous decisions taken or to be taken
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 30 Jul 87 06:12:35 PDT
Received: from [128.89.1.80] by RELAY.CS.NET id aa02415; 30 Jul 87 9:08 EDT
Received: from ti-csl by RELAY.CS.NET id ad12225; 30 Jul 87 9:02 EDT
Received: from Jenner by tilde id AA02135; Thu, 30 Jul 87 07:59:04 CDT
Message-Id: <2763637077-14200445@Jenner>
Date: Thu, 30 Jul 87 07:57:57 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Msg of Wed, 29 Jul 87 16:25:25 -0700 from kempf%hplabsz@hplabs.hp.com
> We need to decide whether class-name of an anonymous class is nil.
Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
second. An anonymous class should be a class with NO name.
If we signal an error on class-name, then we have to come up with a
predicate to test if the class is named or not. Is it worth the trouble?
Additionally, it would be nice if
top level forms would also print out something at compile time. Our
applications developers are asking for some feedback about what gets
done at compile time. Maybe that's an implementation issue, though.
You're right, it is an implementation issue, some compilers have a
verbose option.
> 2-13 class-named needs a new name for consistency. get-class would be wrong
> because the other get-xxx functions aren't name operations. symbol-class
> is the agreed name. It needs an environment argument. The errorp argument
> gets in the way. I think we agree that symbol-class should be setf'able,
> but can it only be set once for a given symbol or is it allowed to change
> the symbol-to-class-object mapping?
Why an environment argument? Since we haven't agreed to lexically scoped
class names, this would seem unnecessary. Is it to deal with the ERRORP
argument? Why do people think it will get in the way? Why not just make
it a keyword argument? A user might want to not have it signal an error
especially in metaclass programming. If whether or not it signals an
error is dependent on a (second-class) environment argument, then it
will be more difficult for a user to arrange. I think the name SYMBOL-CLASS
is OK, and that it should be allowed to change the
symbol-to-class-object mapping.
The important thing in CLOS is the object, and the name to object mapping
should be changable.
The environment argument will be necessary to address the compile
environment problem. The term might be confusing, it is not necessary
an environment like the &environment argument in a macro definition.
> What can be done with method objects, e.g. can one method be added
> to more than one generic function?
There may be a problem if the method invokes CALL-NEXT-METHOD. This
relates back to whether CALL-NEXT-METHOD is dynamic or indefinite
in extent. If it is dynamic, then there should be no problem, since
the binding of CALL-NEXT-METHOD is done when the method begins executing,
at the latest, or during calculation of the effective method, at the
earliest. Thus the same method object on multiple generic functions
would be no problem, since that case could be detected and establishment
of CALL-NEXT-METHOD's binding deferred as late as possible. If the
extent is indefinite, then the binding could potentially remain outside
of a particular method invocation, and so adding the same method to
more than one generic function may cause a problem.
> Which symbols defined by the standard go in what package?
> July: I think we said some will go in LISP: and some will go in CLOS: and
> we don't know yet where to draw the line.
I think they should all go into CLOS, except those which are already in
LISP (like DOCUMENTATION) or those which are designed to replace aspects
of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
We said that some of the symbols will go to LISP because CLOS is
supposed to be part of ANSI Common Lisp. The top level macros and
functions should be part of LISP. The internal functions specified for
the sake of metaclass programming can reside in CLOS.
> Gregor doesn't like the ability to specify constraints on the ordering
> of classes that only apply conditionally, i.e. if those classes are
> actually present among the superclasses. He considers this bad style.
> Moon volunteered to write a proposal with some examples, and we agreed
> to resolve this over the mail.
I agree with Gregor. I think that user specified changes in the CPL
should be controlled through COMPUTE-CLASS-PRECEDENCE-LIST, or, if
the default algorithm can't make a decision.
Let's see what Moon's proposal before discussing the issue.
> I'm not sure if we said anywhere what happens when you call a generic
> function and there is no applicable method; I think it ought to signal
> an error.
Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
in the context of Dick's proposed error naming scheme.
If we can assume that the ANSI will standardize an error handler then I
am in favor of signalling an error and specifying the signal name. If
we can't assume that, I would rather call a generic function like
NO-MATCHING-METHOD.
∂30-Jul-87 1306 Bobrow.pa@Xerox.COM Re: Name That Class
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 30 Jul 87 13:06:15 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 29 JUL 87 18:36:33 PDT
Date: 29 Jul 87 18:36 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Name That Class
In-reply-to: Gregor.pa's message of 28 Jul 87 19:21 PDT
To: Gregor.pa@Xerox.COM
cc: RPG@SAIL.STANFORD.EDU, common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870729-183633-103@Xerox>
I support proposal 3
(setf(class-named <symbol>) <class>)
and
(class-names <class>)
for the reasons given
danny
∂31-Jul-87 0939 kempf%hplabsz@hplabs.HP.COM Re: Miscellaneous decisions taken or to be taken
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Jul 87 09:38:35 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 30 Jul 87 15:21:28 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 30 Jul 87 15:21:04 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 30 Jul 87 16:21:49 pdt
Message-Id: <8707302221.AA01264@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellaneous decisions taken or to be taken
In-Reply-To: Your message of Thu, 30 Jul 87 07:57:57 -0500.
<2763637077-14200445@Jenner>
Date: Thu, 30 Jul 87 16:21:46 MST
From: kempf%hplabsz@hplabs.HP.COM
> > We need to decide whether class-name of an anonymous class is nil.
>
> Two choices are 1) NIL 2) CLASS-NAME signals an error. I vote for the
> second. An anonymous class should be a class with NO name.
> If we signal an error on class-name, then we have to come up with a
> predicate to test if the class is named or not. Is it worth the trouble?
This is a problem. Also with unnamed generic function objects, and
methods. In the interest of simplicity, I'd be willing to forgo this.
I can't think of why anyone would want to name a class NIL anyway.
> The environment argument will be necessary to address the compile
> environment problem. The term might be confusing, it is not necessary
> an environment like the &environment argument in a macro definition.
>
We need some more discussion on this first. I agree that the the compile
environment problem needs solution (especially for single address space
implementations) but I'd rather see some concensus on a general solution
before bringing up specific functions. Even if it means having to revise
the parameter lists of some functions.
>
> I think they should all go into CLOS, except those which are already in
> LISP (like DOCUMENTATION) or those which are designed to replace aspects
> of LISP already existing (like PRINT-OBJECT). Very few are in these categories.
>
> We said that some of the symbols will go to LISP because CLOS is
> supposed to be part of ANSI Common Lisp. The top level macros and
> functions should be part of LISP. The internal functions specified for
> the sake of metaclass programming can reside in CLOS.
Does this mean that a decision was made at the July meeting on the point
Pavel Curtis raised at the March meeting about what relationship CLOS
should have with the full language standard? Unless implementors of
Common Lisp are required to implement CLOS in order to have "full
ANSI Standard Common Lisp", I think it would be better to allow some
flexibility in where the symbols go.
> > I'm not sure if we said anywhere what happens when you call a generic
> > function and there is no applicable method; I think it ought to signal
> > an error.
>
> Yes, and CALL-NEXT-METHOD should do the same. Again, we need to clarify
> in the context of Dick's proposed error naming scheme.
> If we can assume that the ANSI will standardize an error handler then I
> am in favor of signalling an error and specifying the signal name. If
> we can't assume that, I would rather call a generic function like
> NO-MATCHING-METHOD.
I agree with your preferences here. The error message should also give some
information about the classes of the parameters, in addition, to help
debugging.
∂31-Jul-87 1110 kempf%hplabsz@hplabs.HP.COM TRACE Proposal (Version 1)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Jul 87 11:09:44 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Fri, 31 Jul 87 11:07:37 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 31 Jul 87 11:07:05 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 31 Jul 87 12:07:43 pdt
Message-Id: <8707311807.AA10361@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: TRACE Proposal (Version 1)
X-Mailer: mh6.5
Date: Fri, 31 Jul 87 12:07:37 MST
From: kempf%hplabsz@hplabs.HP.COM
As promised, here is an initial draft of a proposal for modifying the
TRACE macro (CLtL, pp. 440-441) to better support object-oriented
programming. The proposal is motivated by the expressed need of our
applications programmers. Sometimes, they would like to only trace
when a particular method is run, rather than tracing every method
when the generic function is invoked. Additionally, some constructs
in Common Lisp which are usually implemented as functions (macroexpansions,
SETF's) are currently not tracable through the TRACE function, but rather
require extra effort. There is obviously lots of room for implementation
dependency here, and some things which would be nice to do portably
(like tracing local function invocations) are difficult because Common
Lisp doesn't have the right constructs (like no first class environments).
The proposal is a combination of Moon's function spec idea, at the
programmer interface level, and Danny's generic function idea, at the
system level. I think most Common Lisp implementors probably include
some help for tracing methods already, if they implement an object-oriented
language.
---------------------------------------------------------------------------------
TRACE &REST {function-spec}* [Macro]
Invoking TRACE with one or more function specifications causes the
functions specified to be traced. Henceforth whenever a specified
function is invoked, information about the call, the arguments passed,
and the returned values, if any, will be printed to the stream that is
the value of *TRACE-OUTPUT*.
A function-spec is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a function specification type, and
whose tail indicates which particular function of that type should
be traced. The complete set of function specification types will
necessarily be implementation specific, but all implementations
are required to provide the following:
<symbol>-Invocation of the function named by <symbol> via. <symbol>'s
global function cell are traced.
(:SETF <place> )-If the generalized variable reference indicated by
<place> is tracable, then invocations of the function implementing
the SETF operation will be traced.
(:METHOD <generic-function-name> <parameter-specializer-name-list>)-
If the method whose parameter specializer list and generic function
are indicated in the specification is tracable, then invocations
through the generic function name will be traced.
(:MACRO-FUNCTION <symbol>)-If <symbol> has a global function definition
that is a macro definition, then invocations of the macro function through
<symbol> will be traced.
>>>>others? Some which I can think of that might be useful are:
(:LOCAL <symbol> <environment>)-Invocations of the function named
<symbol> when the current environment is <environment> are traced.
Problems: Environments are second-class in Common Lisp. Something similar
would be:
(:LOCAL <global-function-symbol> <local-function-symbol>)-Same, except
would get at the environment via. a global function name. This won't take
care of FLETS inside FLETS, nor of FLETS at the top level, however.
This could also be potentially handled via. the macro's environment
parameter.
(:FUNDEF <function definition object>)-Invocations of the function
definition object are traced, regardless of whether they are through
a global or local name symbol.
Problems: Wrapping the function to trace invocation may require modifying the
function definition object, which may not be possible in all
implementations of Common Lisp.
Slot initialization functions, and lambdas are other items which need
consideration.
Note: Another useful enhancement would be to support a :BREAK flag, like
this:
(:METHOD <spec> :BREAK)
indicating that a break loop should be entered before and after the
function executes. Most implementations support this, but it is not
in CLtL. This may be an issue for the cleanup committee, however.
<<<<<<<<<<
TRACE-EXECUTION object &OPTIONAL env [Generic Function]
TRACE-EXECUTION discriminates on object to select an implementation
specific method that arranges for the executable entity associated
with object to be traced. The optional env environment parameter is for
those implementations which require environmental information to
arrange for tracing to occur. Implementations are required to provide
TRACE-EXECUTION as the system level entry point for implementing trace
functionality.
The exact nature and number of methods associated with TRACE-EXECUTION
will differ, depending on what function specifications are supported
by TRACE, but every implementation needs to support the following:
SYMBOL-The function indicated by the symbol will be traced when invoked
in the environment. If the function is a macro, then tracing will occur
when the macro function is invoked. If the function definition is bound to
the symbol's global function definition cell, then invocations of
the function via. its global name will be traced. If the function is a
local function, then only invocations when the environment parameter is
the current environment will be traced, provided the implementation can
arrange for it.
METHOD-The method function is traced when invoked.
GENERIC-FUNCTION-The generic function is traced when the discriminator
code is invoked.
FUNCALLABLE-STANDARD-CLASS-???? need more information about what
this is.
>>>>>>>>>others? Some which I can think of are:
FUNCTION-Invocation of the function is traced, regardless
of whether invocation is through a named symbol. This will obviously
depend on whether modifications in fundefs are allowed to support
tracing.
∂02-Aug-87 1725 RPG Miscellenia
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
``p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.''
I am willing to write up a proposal for this, basing it on our latest
thoughts from the mail, if people wish. I do not feel strongly about
this at the moment.
Moon writes:
``p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"''
I believe we originally tried to be consistent with all other DEF<mumble>s
in returning a name. I believe we decided it was ok to return an object
in CLOS DEF<mumble>s.
[Note: Hackers are proud of having invented the `mumble' convention. However,
there is rarely anything new under the sun. Here is a quote from the Saturday,
August 25, 1753 Adventurer by Samuel Johnson:
``I remember,'' says he, ``it was on just such a morning as
this that I and my lord Mumble and the Duke of Tenterden were
out upon a ramble....''
``Tenterden'' is someone who tends a den.]
-rpg-
∂03-Aug-87 1656 kempf%hplabsz@hplabs.HP.COM Re: Miscellenia
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 3 Aug 87 16:56:04 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 3 Aug 87 15:32:53 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 3 Aug 87 15:32:17 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 3 Aug 87 16:33:03 pdt
Message-Id: <8708032233.AA06651@hplabsz.hpl.hp.com>
To: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Miscellenia
In-Reply-To: Your message of 02 Aug 87 17:25:00 -0700.
Date: Mon, 03 Aug 87 16:32:57 MST
From: kempf%hplabsz@hplabs.HP.COM
>
> ``p1-17 "It is currently under discussion whether to provide constructs
> for giving generic functions local names." Do we want to have this
> discussion, or to punt on this syntax. I recall we did come up with some
> reasonble semantics for a GFLET and GFLABELS.''
> I am willing to write up a proposal for this, basing it on our latest
> thoughts from the mail, if people wish. I do not feel strongly about
> this at the moment.
I also don't feel strongly about it at the moment, but a proposal would be
good, if other people agree. Originally, there was some talk about a
GFLAMBDA, but that didn't seem to make it into the document. If you're
open for suggestions, a useful primitive that might address all these
uses might be GFUNCTION, similar to the FUNCTION special form, except
it takes multiple lambda's as arguments.
> [Note: Hackers are proud of having invented the `mumble' convention. However,
> there is rarely anything new under the sun. Here is a quote from the Saturday
,
> August 25, 1753 Adventurer by Samuel Johnson:
> ``I remember,'' says he, ``it was on just such a morning as
> this that I and my lord Mumble and the Duke of Tenterden were
> out upon a ramble....''
> ``Tenterden'' is someone who tends a den.]
Interesting. My English friends tend to use "doobrey" as an unbound in
similar circumstances, viz. DEF<doobrey>. Perhaps, in the 200 odd years
since we've been independent, the language has diverged, like the
pronounciation of "clerk".
I used to occasionally use "X" as an unbound, but, thanks to
Bob Schieffler, that's out now.
jak
∂04-Aug-87 2243 kempf%hplabsz@hplabs.HP.COM Re: Technical corrections in 87-002
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 4 Aug 87 22:43:16 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 4 Aug 87 14:52:14 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 4 Aug 87 14:51:51 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 4 Aug 87 15:52:31 pdt
Message-Id: <8708042152.AA10558@hplabsz.hpl.hp.com>
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, olthoff%hplabsz@hplabs.HP.COM
Subject: Re: Technical corrections in 87-002
X-Mailer: mh6.5
In-Reply-To: Your message of 28 Jul 87 15:02:00 -0700.
<870728-150405-2277@Xerox>
Date: Tue, 04 Aug 87 15:52:27 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry it's taken so long to answer this.
JAK> As a counterexample, consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4
JAK> c6)}
This is, in fact, incorrect, as Danny pointed out. It should be:
R = { (c1,c2),(c2,c3),(c3,c4),(c3,c5),(c4,c6) }
by the algorithm at the top of pg. 1-14. But see below for more.
JAK> The inheritance graph for this is;
JAK> c5 c6
JAK> | |
JAK> c3 c4
JAK> | |
JAK> \ /
JAK> \ /
JAK> c2
JAK> |
JAK> c1
DB> This counterexample is wrong in that the inheritance graph must specify
DB> a local ordering of c3 and c4 (if vertical means direct superclass and
DB> horizontal is an ordered list.
The intention was that the numbers would indicate the local precedence
ordering. Thus the CLOS definitions would look like:
(defclass c6 () ...)
(defclass c5 () ...)
(defclass c4 (c6) ...)
(defclass c3 (c5) ...)
(defclass c2 (c3 c4) ...)
(defclass c1 (c2) ...)
In fact, the counterexample is wrong, but the interesting fact is
WHY. The counterexample was generated by looking at the pie example
on pg. 1-15, where R is given as:
R = { (pie,apple) (pie,cinnamon),(apple,cinnamon),(apple,fruit),
(cinnamon,spice),(fruit,food),(spice,food),(food,t)
}
However, this is incorrect. The correct value of R before the start
of CPL construction is:
R = { (pie,apple),(apple,cinnamon),(apple,fruit),(cinammon,spice),
(fruit,food),(spice,food),(food,t)
}
This follows by merging the R(C) for each of the classes:
R(pie) = { (pie,apple),(apple,cinnamon) }
R(apple) = { (apple,fruit) }
R(cinnamon) = { (cinnamon,spice) }
R(fruit) = { (fruit,food) }
R(spice) = { (spice,food) }
R(food) = { (food,T) }
Thus the entry (pie,cinnamon) in R is incorrect, and leads to a lack
of the local precedence order being reflected in R.
The R in the counterexample was constructed directly from this example.
Perhaps someone has noted this before and corrected it. In any event,
I suspect that some of the confusion expressed by Sherlis and others
at the March meeting may have been a result of trying to understand
the algorithm via the example. We have had several people here run
into that problem.
DB> The partial order relationship that Dick defines is the one using the
DB> relation "is the same or is subclass of" This one is reflexive, though
DB> we don't have a simple name for it.
This relationship should be sufficient, but I think it should be
made explicit on the top of pg. 1-14. We need not have a simple name,
as long as it is defined. Leaving it implict leaves room for confusion.
I hope whoever is the current custodian of 87-002 can make these corrections.
jak
∂05-Aug-87 1751 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 5 Aug 87 17:51:40 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 05 AUG 87 17:48:48 PDT
Date: 5 Aug 87 17:48 PDT
From: Kelley.pa@Xerox.COM
Subject: Re: ECOOP Reaction to CLOS
In-reply-to: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>'s message of Thu, 9
Jul 87 13:24:38 pdt
To: kempf%hplabsz@hplabs.HP.COM
Cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870805-174848-5665@Xerox>
In dealing with the intractability of the effect of the proposed CLOS
mechanism for multiple inheritance, violation of the "implicit
inheritance - explicit override" rule should be factored out of the
complexity of the linearization algorithm. Each contribute to the
complexity of the CLOS proposal, but hopefully by distinguishing them
and dealing with each seperately, the total complexity can be reduced.
The CLOS proposed standard explicitly claims in general to obey the
implicit inheritance - explicit override rule, but it does not for
multiple inheritance of slots and methods with the same name. Instead,
it actually reverses the rule in this case. Overriding is implicit and
one must explicitly inherit (via qualifiers).
In as much as implicit inheritance is a sub-conscious assumption of
application programmers, standard CLOS behaves in a counter intuitive
manner.
(defclass border (object) (width))
(defmethod close (b border) ...)
(defclass window (object) (width))
(defmethod close (w window) ...)
(defclass bordered-window (border window))
(setq b-window (make-instance 'bordered-window))
(close b-window) ; with the current inheritance algorithm, only closes
the border. Does not close the window.
The following explores what could happen if the implicit inheritance -
explicit override rule were followed in CLOS.
(close b-window) would result in both the border and window close
methods getting called because it inherits them implicitly and has not
explicitly overridden them.
With implicit inheritance a class may have in addition to multiple
methods with the same name that all get called by one call, multiple
occurrences of a slot with the same name that are manipulated in one
operation so b-window would contain two slots named width.
(setf (slot-value b-window width) 0)
Would set both slots to 0.
A problem is what to do with the results of an operation on a slot name
that refers to two or more slots or on a call that refers to two or more
methods. Operating on these slots or methods that have not been
overridden could be specified to return a "multiple-inheritance-result"
object containing the multiple results.
Any code that depended on the results from instances of singly inherited
classes would not work correctly with instances of multiply inherited
classes. (In the example above, any code that depended on the value
returned by the "close" method on an instance of the window class would
not work on an instance of the bordered-window class.) A blatant error
would usually be generated at run time. A warning of potential such
behavior at definition time might be a desireable feature.
All the unqualified inherited methods with the same name would still
have to get executed in some order. However, it would be possible to
simply specify that these operations are executed in a random order.
-- kirk
∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellenia
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 12:48:53 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208062; Thu 6-Aug-87 13:55:31 EDT
Date: Thu, 6 Aug 87 13:55 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellenia
To: Common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 2 Aug 87 20:25 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870806135534.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 02 Aug 87 1725 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Moon writes:
``p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.''
I am willing to write up a proposal for this, basing it on our latest
thoughts from the mail, if people wish. I do not feel strongly about
this at the moment.
Please do write the proposal. But I wouldn't consider this high priority
at the moment, since you don't feel strongly about it and no one else has
said they feel strongly.
∂06-Aug-87 1249 Moon@STONY-BROOK.SCRC.Symbolics.COM TRACE Proposal (Version 1)
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 12:49:12 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208071; Thu 6-Aug-87 14:09:57 EDT
Date: Thu, 6 Aug 87 14:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: TRACE Proposal (Version 1)
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU, Masinter.pa@XEROX.COM
In-Reply-To: <8707311807.AA10361@hplabsz.hpl.hp.com>
Message-ID: <870806141000.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: Fri, 31 Jul 87 12:07:37 MST
From: kempf%hplabsz@hplabs.HP.COM
As promised, here is an initial draft of a proposal for modifying the
TRACE macro (CLtL, pp. 440-441) to better support object-oriented
programming....
This looks interesting. I have a couple of comments to offer right now.
A function-spec is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a function specification type, and
whose tail indicates which particular function of that type should
be traced.
The Cleanup subcommittee of X3J13 were discussing something similar
a while back, starting from a different point. The DOCUMENTATION function
of Common Lisp introduces the concept of "definition types", and this
concept could be useful in other operations. For instance, it would be
nice to be able to remove any definition (function, variable, type, setf)
through a uniform interface. "Definition type" and "function spec type"
are not the same concept, however there seems to be enough overlap here
that some coordination is probably called for.
I don't remember for sure, but I think Larry Masinter volunteered to make
a proposal for "definition types" when he got time.
....
Note: Another useful enhancement would be to support a :BREAK flag, like
this:
(:METHOD <spec> :BREAK)
indicating that a break loop should be entered before and after the
function executes.
Here you see a conflict between lists as function-specs and lists as
lists of options, in the arguments to TRACE. Because of this your proposal
for TRACE is not compatible with what Symbolics currently does, but I don't
think that's too important for us. We say that a list is a list of options,
and if you want to trace a function whose name is a list, you have to do
(TRACE (:function <function-spec> <options>...)). But all this really
shows is that the syntax of TRACE is ridiculous. I usually ignore the TRACE
function and trace things through a command interface. Anyway, for your
proposal you have to decide between lists as function specs and lists as
options; I don't think you can mix them freely as you proposed. Of course
it would be a lot easier if TRACE only traced one function at a time,
then the rest of the form could be used for options. That would be a bit
incompatible with CLtL.
TRACE-EXECUTION object &OPTIONAL env [Generic Function]
I didn't completely understand this. It looks like there is some
incoherence about whether TRACE is an operation on functions or on
places in which you can store a function definition. In other words,
does tracing a function redefine the function or alter the object that
is the function's definition? In other words, does
(defun foo () ...)
(setq f #'foo)
(trace foo)
(funcall f)
generate trace-output or not? We have to decide one way or the other.
CLtL is obscure on this point.
∂06-Aug-87 1914 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Name That Class
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 19:14:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208497; Thu 6-Aug-87 22:14:54 EDT
Date: Thu, 6 Aug 87 22:14 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Name That Class
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870728-192157-1316@Xerox>
Message-ID: <870806221457.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 28 Jul 87 19:21 PDT
From: Gregor.pa@Xerox.COM
It seems to me that there are ways for class-named and setf of such to
work. I think only two of these are reasonable, but I will include the
third for completeness. Note that this same analysis applies to
generic-function-name and setf of symbol-function and
get-setf-generic-function. I will do class names first.
A class C 'is bound to' a given name Ni iff (class-named Ni) returns C.
In all this solutions, we document class-named and setf of class-named.
We say that class-named returns the class is bound to a particular name.
We say that setf of class-named can be used to set the binding of a
class to a name.
All agreed, except I think we decided a month ago to rename class-named to
symbol-class, to be more consistent with the rest of Common-Lisp.
Solution 1:
Only document class-named and setf of class-named. Most
implementations will have some magic for printing out a class's name
when it has one.
Solution 2:
Document class-named and setf of class-named. Also document
class-name, but say that the the class may or may not 'bound' to that
name.
Solution 3:
Document class-named and class-names and setf of class-named. Say
that setf of class-named can be used to bind a clas to a name. Say that
class-names returns the list of all names that a class is bound to.
It seems to me that solution 1 and solution 3 are the only reasonable
ones. My general dislike of names makes me prefer solution 1, but I
think that solution 3 actually provides users some important
functionality.
That's interesting, because I prefer solution 2, for the simple reason
that everything else I can think of that has a name works that way. The
symbol->object mapping is the "real" one, and the object->symbol mapping
is only a helpful hint for printing things out, but isn't necessarily kept
consistent with the symbol->object (a programming environment might try
to keep it consistent).
As far as I am concerned, any of these three would work. My objection
to solution 3 is primarily that it is more complicated. My objection to
solution 1 is that it is the same as solution 2 as soon as the users
discover what the name of the class-name function is, and no useful
purpose is served by making this name implementation-dependent.
....
(setf (class-named 'n1) nil)
#<Standard-Class N2 1>
Is this really how we want to undo these bindings? Nothing else in Common
Lisp I can think of works this way (storing nil). Also, a minor nit, CL
requires that such a setf form return nil, not the former value.
I think its easy to see how this whole thing would work for
generic-function-name, symbol-function, setf of symbol-function,
get-setf-generic-function and setf of get-setf-generic-function.
Agreed. Note that (setf (symbol-function 'foo) nil) isn't how we do
(fmakunbound 'foo) in CL currently.
∂06-Aug-87 1929 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 6 Aug 87 19:29:18 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 208512; Thu 6-Aug-87 22:29:57 EDT
Date: Thu, 6 Aug 87 22:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870727224638.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870806223002.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July and on mail received
in response to the last time I mailed this out (about two weeks ago).
If anyone doesn't see their response included, or thinks their favorite
issue is missing, please let me know and I will apologize for my error
and add it. I hope that we can use this file to help drive progress.
The major issues of object creation and class redefinition are not in
here, being handled individually.
The rest of this message is the file. Page separator characters don't
seem to go through, so I have replaced each with 16 equal signs.
This page is things that I think we agreed that we had decided
after the March meeting and before the July meeting.
27 May 87 call-next-method is allowed to take arguments, however it is
an error to give it arguments that would change the set of applicable
methods. I think we're saying this signals an error, and mentioning
that in some simple cases the lack of need for an error check can be
proved at compile time, but in general a run-time check is required.
Specify precisely the type of error signalling.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on that?
Patrick agrees 7/29/87. It's in the document file now.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
Kempf agrees they should return the object. Moon isn't sure, because
defun, defvar, deftype, and defstruct return the name. As far as I can
tell every defxxx form in CLtL returns the name. The problem is that
we haven't admitted that defmethod has a name.
In July we decided (for the previous three) to return the object for
all CLOS defxxx functions (being inconsistent with Common Lisp, but
consistent within CLOS). The document file has been updated.
================
This page is a list of issues on which we should make decisions,
brought up by Danny. Where I saw responsive answers in the mail
(there were very few) I have edited them in. I've removed comments
that were purely editorial comments on the document.
p1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Kempf says you shouldn't be allowed to change the metaclass, because
the representations might differ and existing instances might not
be transformable.
Gregor says the metaclass protocol includes a predicate function
that controls this, and Patrick and Jim agree.
p1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonble semantics for a GFLET and GFLABELS.
In July we decided to defer this.
2 Aug 87 RPG offered to write a proposal.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
p1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
See additional discussion of class names below (2-13).
We need to decide whether class-name of an anonymous class is nil or
signals an error.
The concensus seems to be to return nil.
p2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. Then we said we'd discuss it further in the mail.
I think we agreed that the turning of two setf argument lists into one should
depend only on the argument lists, and not on the generic function object.
[My notes include an illegible comment, I think it means that I still hope
we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one. But maybe it means that
we will document it, but still have defmethod-setf so that most users
don't have to think about it (only users making setf methods "directly").]
p2-39 Arguments: "list of t's" should be replaced by "list whose elements are
the class named t" since get-method only takes specializers, not names of
specializers.
Agreed.
p2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
p2-51 print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
I suppose the default method signals a condition of the same name?
Gregor will propose the details.
================
This page is a list I made in March, keyed by page numbers in the document.
Issues mentioned earlier, or that have since died, have been removed. I've
removed comments that were purely editorial comments on the document.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
2-13 class-named needs a new name for consistency. get-class would be wrong
because the other get-xxx functions aren't name operations. symbol-class is
the agreed name. It needs an environment argument to deal with the issue of
compile environment versus run-time environment. The errorp argument gets in
the way, because it's an optional argument--we could get rid of it, or we
could make both arguments keywords. I think we agree that symbol-class
should be setf'able, but can it only be set once for a given symbol or is it
allowed to change the symbol-to-class-object mapping?
Kempf: Need consensus on a general solution of the compile environment
issue before fixing individual functions such as symbol-class.
The symbol-to-class-object mapping should be changeable.
Bobrow: symbol-class should be setf'able.
Gregor: setf'able. Issue is consistency of symbol-class with class-name.
1) No class-name. 2) No consistency. 3) class-names returns a list of
names and setf of symbol-class maintains it. 2 is unreasonable.
I like 1 but 3 is good too.
(setf (class-named 'n1) nil) is how you undo the binding.
Note that this same analysis applies to generic-function-name and
setf of symbol-function and get-setf-generic-function.
Bobrow: I like 3.
Moon: class-names would need an environment argument too.
I guess any of these is okay but 2 is how everything else works.
I don't like undoing the binding by setting to NIL (CL Cleanup
may propose a general mechanism for undoing named definitions).
2-16 (slot-name form) should be allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
but it never finds its way into the document.
In July we rejected this. Since people keep assuming it, we have
to document explicitly that it is not allowed.
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
Kempf: it should signal an error.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-40 get-setf-generic-function needs an errorp, but it and ensure-generic-function
should be subsumed by get-generic-function which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Or was it called ensure-generic-function?
Gregor promised to mail out the proposal.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
================
Documented holes in chapters 1 and 2 of 87-002. We publicly promised
X3J13 that we would finish these and have a new draft of 87-003 by the
next meeting.
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
Document has been updated in draft.
Need Cleanup Committee proposals for fixes to the type system.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
This may not have been put into the document yet.
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
================
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Kempf: There may be a problem if the method invokes CALL-NEXT-METHOD.
[I wasn't able to understand his description of the problem -- Moon]
Ida: make-specializable seems to be missing
Gregor's proposal for ensure-generic-function will subsume this.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
To be resolved as part of the initialization protocol discussion.
Should we just flush multiple-value-prog2, as leading to more discussion
than is warranted by its simplification of the presentation of
define-method-combination?
Kempf: Yes.
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
The top level macros and functions should be part of LISP.
The internal functions specified for the sake of metaclass programming
can reside in CLOS.
If CLOS is an optional part of CL, are the symbols in the LISP package
even when the option is not present? Probably.
Should we flush defmethod-setf and friends in favor of function specs?
It probably turns out they could be just in the macros and not in the
underlying Lisp. The big issue is standardizing where the "new-value"
argument goes; but we may do that anyway (mentioned earlier in this file).
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe?
Kempf: I think we ought to keep DEFMETHOD-SETF, but use function specs (or
something like them) as the programmer interface to TRACE.
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
The fact that symbol-function (the user callable primitive) needs to
be split from the subprimitive for implementators that gets and sets
the "real" function definition of a symbol. This is so when a symbol's
function definition is a generic function object, the "real" definition
can be something that is easier for the implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
Kempf: I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations.
Moon: Right, the only standardization issue is making sure
SYMBOL-FUNCTION returns the generic function object, not something internal.
See earlier discussion of class-names (2-13), which affects symbol-function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor volunteered to send some mail about this.
CALL-NEXT-METHOD with no more methods should do something similar,
but not identical.
We could call a generic function like NO-MATCHING-METHOD, but it would
be better to signal a condition (assuming conditions are adopted into
Common Lisp). The error message should give some information about
the classes of the parameters, to help debugging.
Clarify that because class names and classes are type-specifiers, they can be
validly be used in THE special forms and in TYPE declarations. We forgot this
when we clarified that class objects can be used with TYPEP and SUBTYPEP.
July: agreed
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
Need to be able to get at the obsolete classes associated with a class,
to put methods on them.
Patrick has proposed.
Need discussion of how instances are transformed one step at a time
when a class has been redefined multiple times.
Not all of the "corrections and amendments" handed out at the March 1987
X3J13 meeting in Palo Alto have been put into the document yet. The
corrections are in but the amendments and the revised explanation of slot
inheritance are awaiting review by the group.
Kempf 29 Jul 87: There was no mention made of compile time optimization,
which I believe I made some initial proposals on in late April or early May.
I've been meaning to revisit them.
2-30: Note the third paragraph on p.2-30 of 87-002, speaking of signalling an
error when the arbitrary order of two methods affects the result. I suggest
that this error be mandatory instead of optional.
∂09-Aug-87 1514 Gregor.pa@Xerox.COM Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Aug 87 15:14:01 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 09 AUG 87 15:14:26 PDT
Date: Sun, 9 Aug 87 15:14 PDT
From: Gregor.pa@Xerox.COM
Subject: Miscellaneous decisions taken or to be taken
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870809151423.5.GREGOR@SPIFF.isl.parc.xerox.com>
Line-fold: no
Date: Thu, 6 Aug 87 22:30 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on my notes from the meeting we had in July and on mail received
in response to the last time I mailed this out (about two weeks ago).
In the usual way, I have included only parts of your message on which
I am making specific comments. In several places I have sketched
proposal which were on my to do list. I am about to go away for a
week and don't have time between now and then to flesh these
proposals out, but I think they are fairly clear from the sketches.
10 June 87 There was no response when Sonya mailed out a writeup for how
the standard type classes are organized. Does that mean we agreed on
that?
Patrick agrees 7/29/87. It's in the document file now.
I have it on my list of things to do to come up with a picture of how
all the standard classes (including standard type classes) are
organized. I have this on the whiteboard in my office now. In a
separate message, I will send out the name of a press file which
contains a simple version of such a picture. If people could FTP
that press file and try printing it, then I could now if its worth
trying to cast the whole picture in that format.
p1-18 It is not specified whether get-setf-generic-function is a
setf-able form. I suggest that it be made so. This would allow one to
trace setf-generic-function's without having to know their names.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
Yes, I believe get-setf-generic-function should be a setfable form
with the same provision as Moon mentions. The way to think of
get-setf-generic-function is just like symbol-function and
symbol-class. (This may mean that it would be appropriate to rename
it to symbol-setf-generic-function.) Later in this message, I will
make some other comments which address this issue.
p1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. I'm not sure what operations on that list,
besides checking its length, would be permitted.
I am not sure what you mean by this. Surely other non-destructive
operations would be legal as well. For example, one could implement
some sort of "tracing" :around method by having it get the list of
next methods, and calling each of their functions. But clearly it
would not be legal to rplaca or rplacd that list.
2-13(?) The generic function class-name is not written up. It returns a
name for the class as argument. I believe that (class-name class)
should be setf-able. Can a class have more than one name? Should
class-name then return a second argument -- the rest of the names this
class is known by.
Kempf thinks the class name should be changeable and only one name
at a time should be allowed. Moon agrees.
See additional discussion of class names below (2-13).
As I said in another message, I don't believe class-name should be
setfable. symbol-class (nee class-named) should be setfable, it is
possible that it should update class-named as well, the details of
how that updating might work were the subject of my other message.
Even if we decide that class-name should return at most one name, I
think it is clear that a class can have more than one name. That is,
it is legal to use setf of symbol-class to make the multiple symbols
point to the same class.
p2-35 The argument order of the setf method ought to be documented here.
Gregor proposed that new-value be the first argument. Any problem with
this?
Kempf doesn't care but his users want it to be the second argument.
Moon doesn't care but his users are used to it being the last argument.
In July we suggested making the new-value argument a required argument
that comes after all the other required arguments, and before the
optional, rest, and keyword arguments. Then we said we'd discuss it
further in the mail.
I think we agreed that the turning of two setf argument lists into one
should depend only on the argument lists, and not on the generic
function object.
[My notes include an illegible comment, I think it means that I still
hope we can keep things abstract enough that we don't have to document
how the two setf argument lists are turned into one. But maybe it
means that we will document it, but still have defmethod-setf so that
most users don't have to think about it (only users making setf
methods "directly").]
I have several coments.
First, I believe it is very important that this operation only be a
function of the two lambda lists.
Second, I would rather the rules of this operation be documented.
That is, I would not be as happy if we just provided a function
(make-setf-method-lambda-list) which did the work. Providing that
function in addition to documenting its behavior might be a good idea
though.
Third, as we agreed, its fine with me to have it be the last required
argument. But I think we need to be careful how we word this.
Because we have to make it clear what happens in implementations
which have non-standard lambda-list-keywords.
p2-54 slot-missing should be documented
It's a generic function of a class, an object, and a slot name.
I suppose the default method signals a condition of the same name?
Gregor will propose the details.
slot-missing is a generic function which takes three required
arguments and an optional fourth argument. The three required
arguments are the class of the object, the object and the name of the
slot. The fourth argument is the new value for the slot if
slot-missing is being called by setf of slot-value. This set of
arguments allows people to define methods on the metaclass for
handling slot-missing. For example, a low performance implementation
of dynamic slots could work this way.
(defmethod slot-missing ((class dynamic-class) obj slot
&optional (nv nvp))
(if nvp
(set-dynamic-slot obj slot nv)
(get-dynamic-slot obj slot)))
The default method on slot-missing signals an error of the same name.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
I am pretty sure what we meant was we didn't want to have to worry
about the case where someone returns a closure that includes a call
to call-next-method, and then redefines the class or method structure
so that the closure would have to call different 'next methods'.
2-13 class-named needs a new name for consistency. get-class would be
wrong because the other get-xxx functions aren't name operations.
symbol-class is the agreed name. It needs an environment argument to
deal with the issue of compile environment versus run-time environment.
The errorp argument gets in
the way, because it's an optional argument--we could get rid of it, or we
could make both arguments keywords. I think we agree that symbol-class
should be setf'able, but can it only be set once for a given symbol or
is it allowed to change the symbol-to-class-object mapping?
Kempf: Need consensus on a general solution of the compile environment
issue before fixing individual functions such as symbol-class.
The symbol-to-class-object mapping should be changeable.
Bobrow: symbol-class should be setf'able.
Gregor: setf'able. Issue is consistency of symbol-class with class-name.
1) No class-name. 2) No consistency. 3) class-names returns a list of
names and setf of symbol-class maintains it. 2 is unreasonable.
I like 1 but 3 is good too.
(setf (class-named 'n1) nil) is how you undo the binding.
Note that this same analysis applies to generic-function-name and
setf of symbol-function and get-setf-generic-function.
Bobrow: I like 3.
Moon: class-names would need an environment argument too.
I guess any of these is okay but 2 is how everything else works.
I don't like undoing the binding by setting to NIL (CL Cleanup
may propose a general mechanism for undoing named definitions).
If this whole mess isn't an argument for a lisp-1 I don't know what
is. At this point I guess we need:
symbol-class
symbol-setf-generic-function
(both of the above need to be setfable)
(there needs to be a mechanism for making each unbound)
(we need to decide how they interact with class-name and
generic-function-name)
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
The current initialization proposal doesn't have constructors?
2-40 get-setf-generic-function needs an errorp, but it and
ensure-generic-function should be subsumed by get-generic-function
which would do all the right things.
We seem to have lost Gregor's proposal for get-generic-function.
Or was it called ensure-generic-function?
Gregor promised to mail out the proposal.
I propose that we keep get-setf-generic-function, but that we rename it to
symbol-setf-generic-function. In addition, I propose that we do the
following:
ensure-generic-function, add-named-method and any other CLOS
function that takes the name of a generic function as an argument
can also take a list like (SETF <symbol>) which means the
setf-generic function for that argument.
I propose that ensure-generic-function do basically what
defgeneric-options and defgeneric-options-setf used to do except that
ensure-generic-function would be a function (that is it would
evaluate its arguments). This isn't a problem since
defgeneric-options didn't take any &body arguments anyways. The real
thing that needs to be worked out here is what happens if the generic
function already exists, but is different in some ways than the
description in the arguments to ensure-generic-function.
2-57 with-slots :prefix package problem; This was discussed in the mail
and then the ball was dropped. What's in the document is unworkable
because it depends on the dynamic value of *package* at macro-expansion
time, but Common Lisp doesn't guarantee anything about when
macro-expansion occurs. Moon would prefer to flush the :prefix option.
An alternative that was discussed was to use symbol-package of the
prefix, both here and in defclass accessor construction, as the package,
relying on the likelyhood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
I like the prefix option, although I agree that this is a serious
problem.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
What if by the time you actually run the body of the method, the slot
has an accessor. That is to say, what if you do the following:
(defclass foo () (a b c))
(defmethod bar ((o foo)) ;Put this in a file,
(with-slots (o) (list a b c))) ;compile and load it.
(defclass foo ()
(a b c)
(:accessor-prefix foo-))
(bar (make-instance 'foo))
Does this signal an error? It seems to me that the real problem with
this case is the same as the real problem with the above case. It
all hinges on exactly when macro-expansion time is and that is not
specified.
Other issues:
What can be done with method objects, e.g. can one method be added
to more than one generic function?
I believe it should signal an error to attempt to put a method on
more than one generic function. My model of this is that if you want
to do something like that, you can take one function, use it as the
method function of multiple methods, each of which would be on a
different generic function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor volunteered to send some mail about this.
This is a generic function like slot-missing. There is a generic
function NO-MATCHING-METHOD which is called with the generic function
as the first argument and the arguments to the generic function as
the remaining arguments. This allows people to defined method to
handle the no matching method case either on the class of the generic
function or on the individual generic function. The default method
for no-matching-method signals an error of the same type.
-------
∂10-Aug-87 1122 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Aug 87 11:21:44 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 10 Aug 87 11:14:59 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 10 Aug 87 11:14:33 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 10 Aug 87 12:15:19 pdt
Message-Id: <8708101815.AA15913@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Name That Class
In-Reply-To: Your message of Thu, 06 Aug 87 22:14:00 -0400.
<870806221457.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 12:15:15 MST
From: kempf%hplabsz@hplabs.HP.COM
> As far as I am concerned, any of these three would work. My objection
> to solution 3 is primarily that it is more complicated.
In addition to this objection to solution 3, another is that while other things
(particularly functions) can be multiply named, there
is currently no portable way in CL to get the name (or names) of
a function given a function definition object. If we are going to model
class object naming similarly to function naming (as the name SYMBOL-CLASS
seems to indicate) then we should probably be consistent with the way
functions are done, or suggest that a FUNCTION-NAME or a FUNCTION-NAMES
function be introduced which provides similar functionality; otherwise,
people may become confused. But see below for further thoughts.
> ....
> (setf (class-named 'n1) nil)
> #<Standard-Class N2 1>
> Is this really how we want to undo these bindings? Nothing else in Common
> Lisp I can think of works this way (storing nil). Also, a minor nit, CL
> requires that such a setf form return nil, not the former value.
> I think its easy to see how this whole thing would work for
> generic-function-name, symbol-function, setf of symbol-function,
> get-setf-generic-function and setf of get-setf-generic-function.
> Agreed. Note that (setf (symbol-function 'foo) nil) isn't how we do
> (fmakunbound 'foo) in CL currently.
Your observation about undoing bindings is correct, and, again, to maintain
consistency, CMAKUNBOUND would be the way do this if class name to
object binding is modelled on function name to object binding.
We seem to be slowly drifting towards using a name to object binding
for classes which is modelled on the way function name to object bindings
are handled. I wonder how useful the function model is for modelling
class name to object bindings. In particular, is this going to lead to
the proposal of a "class cell" like the "function cell" for a symbol?
Considering the controversy surrounding the latter, I certainly hope not.
Somehow, I would prefer a more object-oriented approach to resolving this
problem. Two ways which I can think of offhand are:
1) Have the class name be a SETFable slot in the class object. SETFing
a class object's name slot to NIL would be equivalent to making the class
anonymous, if we abide by the convention that asking for the name of
an anonymous class returns NIL (as was discussed in another note string).
2) Have the name to class object binding for an entire class be handled
by the metaclass protocol.
Of the two, I prefer the second one, since it gives some flexibility
for users wanting to define new metaclasses, and also gives some potential
for resolving the compile time name to object mapping, since the metaclass
can potentially control this, but perhaps in an implementation dependent
manner.
I'm willing to write up a proposal on this, if there is any interest.
Though I prefer a more object-oriented approach, I think it is important
that the name to object mapping issue be resolved in a way that is self
consistent and consistent with the rest of Common Lisp.
jak
∂10-Aug-87 1145 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Name That Class
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 10 Aug 87 11:45:49 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 152618; Mon 10-Aug-87 14:42:59 EDT
Date: Mon, 10 Aug 87 14:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Name That Class
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
In-Reply-To: <8708101815.AA15913@hplabsz.hpl.hp.com>
Message-ID: <870810144215.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 12:15:15 MST
From: kempf%hplabsz@hplabs.HP.COM
2) Have the name to class object binding for an entire class be handled
by the metaclass protocol.
Of the two, I prefer the second one, since it gives some flexibility
for users wanting to define new metaclasses, and also gives some potential
for resolving the compile time name to object mapping, since the metaclass
can potentially control this, but perhaps in an implementation dependent
manner.
I'm willing to write up a proposal on this, if there is any interest.
I don't understand how this could work. If one is given a class name and
one wants to find the corresponding class object, how do you know what
metaclass is relevant before you have found the class object?
∂10-Aug-87 1419 kempf%hplabsz@hplabs.HP.COM Re: TRACE Proposal (Version 1)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Aug 87 14:18:43 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 10 Aug 87 10:45:16 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 10 Aug 87 10:44:48 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 10 Aug 87 11:45:34 pdt
Message-Id: <8708101745.AA15689@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU, masinter.pa@XEROX.COM
Subject: Re: TRACE Proposal (Version 1)
In-Reply-To: Your message of Thu, 06 Aug 87 14:10:00 -0400.
<870806141000.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 10 Aug 87 11:45:31 MST
From: kempf%hplabsz@hplabs.HP.COM
> A function-spec is either a symbol naming a function (i.e. a symbol
> whose global function cell is bound to a function definition object)
> or a list whose first element is a function specification type, and
> whose tail indicates which particular function of that type should
> be traced.
> The Cleanup subcommittee of X3J13 were discussing something similar
> a while back, starting from a different point. The DOCUMENTATION function
> of Common Lisp introduces the concept of "definition types", and this
> concept could be useful in other operations. For instance, it would be
A definition type would certainly be a nicer way of handling this. It
would unify how to indicate that a particular definition is wanted.
> Note: Another useful enhancement would be to support a :BREAK flag, like
> this:
> (:METHOD <spec> :BREAK)
> indicating that a break loop should be entered before and after the
> function executes.
> Here you see a conflict between lists as function-specs and lists as
> lists of options, in the arguments to TRACE. Because of this your proposal
> for TRACE is not compatible with what Symbolics currently does, but I don't
> think that's too important for us. We say that a list is a list of options,
> and if you want to trace a function whose name is a list, you have to do
> (TRACE (:function <function-spec> <options>...)). But all this really
> shows is that the syntax of TRACE is ridiculous. I usually ignore the TRACE
> function and trace things through a command interface. Anyway, for your
> proposal you have to decide between lists as function specs and lists as
> options; I don't think you can mix them freely as you proposed. Of course
> it would be a lot > e> asier if TRACE only traced one function at a time,
> then the rest of the form could be used for options. That would be a bit
> incompatible with CLtL.
An alternative would be to introduce a BREAK macro:
BREAK &REST {function-spec or definition}* [Macro]
having the obvious functionality. Such a "functional" interface would
avoid having to try indicating everything through one operation. I
just suggested the :BREAK option because this similar to how we currently
do it.
> TRACE-EXECUTION object &OPTIONAL env [Generic Function]
> I didn't completely understand this. It looks like there is some
> incoherence about whether TRACE is an operation on functions or on
> places in which you can store a function definition. In other words,
> does tracing a function redefine the function or alter the object that
> is the function's definition? In other words, does
> (defun foo () ...)
> (setq f #'foo)
> (trace foo)
> (funcall f)
> generate trace-output or not? We have to decide one way or the other.
> CLtL is obscure on this point.
As is usual in CLOS, the idea here was to split trace functionality into
two pieces a) a programmer interface (TRACE) b) a system level or
metaclass protocol function (TRACE-EXECUTION).
With reference to your example, certain implementations may support the
ability to modify function definition objects directly to allow trace
information to be inserted. Thus the FUNCALL in the example could be
traceable. As the base note suggested, these implementations could then
have a function spec (or definition type) for indicating that the function
should be trace through the fundef object rather than through the symbol.
Other implementations may only be able to trace though a wrapper on the
function symbol. The function spec or definition type would be used for
indicating to TRACE what to do, a corresponding TRACE-EXECUTION method
would contain the implementation dependent code to do it.
As to why go to the trouble of having an extra layer, consider a user
who wants to write a method or generic function class for remote procedure
calls. This user would like some way of handling debugging, and a generic
function in the metaclass protocol seems like the right way to do it.
A generic function would provide the system level interface for other
kinds of debugging functionality.
jak
∂11-Aug-87 1504 kempf%hplabsz@hplabs.HP.COM Re: Name That Class
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 11 Aug 87 15:03:36 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 11 Aug 87 15:01:11 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 11 Aug 87 15:00:34 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 11 Aug 87 16:01:15 pdt
Date: Tue, 11 Aug 87 16:01:13 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
Message-Id: <8708112201.AA26864@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Name That Class
In-Reply-To: Your message of Mon, 10 Aug 87 14:42:00 -0400.
<870810144215.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
I said:
Date: Tue, 11 Aug 87 16:01:12 MST
From: kempf@hplabsz
>> 2) Have the name to class object binding for an entire class be handled
>> by the metaclass protocol.
Moon replied:
> I don't understand how this could work. If one is given a class name and
> one wants to find the corresponding class object, how do you know what
> metaclass is relevant before you have found the class object?
and Gregor said (somewhat earlier):
>Even if we decide that class-name should return at most one name, I
>think it is clear that a class can have more than one name. That is,
>it is legal to use setf of symbol-class to make the multiple symbols
>point to the same class.
and Patrick said (even earlier):
>The environment argument will be necessary to address the compile
>environment problem. The term might be confusing, it is not necessary
>an environment like the &environment argument in a macro definition.
I've been rethinking this issue somewhat, and I think we need to consider
how class names will be used. I can see three ways in which
users may need to use class names:
1) In inheritance lists for indicating direct supers,
2) In parameter specializer lists for indicating that particular method
parameters are specialized to particular classes (or their subclasses),
3) For instantiation,
4) For general queries (i.e. system building-"Is this class there?", etc).
There will be more reasons for using class names if metaclass programming
is taken into account. Let's just consider these for the moment and ask
what would happen if a many to one mapping of classes to names (and
vice versa) were allowed.
If multiple names were allowed to be "bound" to a single class object,
then the function CLASS-NAME(S) could potentially return a list.
The function SYMBOL-CLASS (or CLASS-NAMED) could also return a list,
since, for any particular name, there could be multiple class
objects having it. That is, if we have FOO1 and FOO2 bound to two different
class objects, and the following is legal:
(setf (class-name foo1) 'baz)
(setf (class-name foo2) 'baz)
then the following:
(symbol-class 'baz)
should return a list with two elements, with the CAR EQ to FOO1 and the
CADR EQ to FOO2.
What would this mean for user code? For one thing, the following would be
ambiguous:
(defmethod doit ((x baz))
...
)
since there are now two possibilities for the class BAZ. One could argue
that this should mean that the method should be selected if X is
from either class, but that would be expanding the kind of parameter
specializer to boolean selection, and users may begin to demand something
like:
(defmethod doit ((x (or foo1-class foo2-class)))
...
)
which we may want to avoid. Of course, we could always demand that the
user put in the class object directly, to disambiguate, but names are
good for *something*, in this case, as a shorthand for not having to
say something like:
(defmethod doit ( (x (cadr (symbol-class 'baz))) )
....
)
The reason classes are different from functions is because function
definition objects don't have settable names. You can't say:
(setf (function-name fundef1) 'foo)
(setf (function-name fundef2) 'foo)
at least, not in portable Common Lisp (most implementations probably
allow this sort of thing internally). In addition, the inverse mapping
to SYMBOL-FUNCTION (from function definition objects to names, called
FUNCTION-NAME in the above example) is not defined.
With classes, the inverse mapping needs to be defined and settable, and
that is what is compilicating the issue. There are ways to hack around it,
designating one name the principle name, etc., but they all introduce more
machinery that I think most users will want.
Metaclasses could be used to allow multiple names per class only if
the name to class binding were restricted to one to one within a metaclass.
Across metaclasses, multiple names per class could be allowed.
The various ways this would affect the programmer interface are as follows:
1) SYMBOL-CLASS would require an optional metaclass argument, which
would default to STANDARD-CLASS. SYMBOL-CLASS would be used for general
queries, in addition.
2) Inheritance lists would be no problem, since supers must be of
the same metaclass anyway.
3) DEFMETHOD would require additional machinery to specify the metaclass
of the parameters. Possible choices are:
a) A DEFMETHOD option specifying that the parameters must be
from a particular metaclass. This will give problems with
mixing specializers, for example, if specializers of
metaclass STANDARD-TYPE-CLASS are mixed with those of
metaclass STANDARD-CLASS, as is likely.
b) The syntax of specialized lambda lists be expanded to include
some means of indicating that the class is of a particular
metaclass. This is more flexible, but syntatically clumsier.
Something like:
(defmethod doit ((x foo nonstandard-class) y x)
...
)
is what I have in mind. Defaulting to STANDARD-CLASS may help.
c) DEFMETHOD only works with parameter lists whose classes
are from a restricted set of metaclasses. STANDARD-TYPE-CLASS,
and STANDARD-CLASS are obvious candidates. A user wanting to
handle parameters of another metaclass would need to write
their own parameter list parser, and their own top level macro.
4) Instantiation via. MAKE-INSTANCE would require either:
a) An optional metaclass argument,
b) The argument would need to be the class object itself
rather than a symbol,
c) A symbol argument could default to STANDARD-CLASS.
I honestly think that even this is more machinery than most applications
programmers are going to need. Most users are simply going to use the
default metaclass, and won't want to have more than one name per class
or more than one class per name.
But, as Patrick has pointed out, the issue is more complex. The name
to class (or name to generic function) binding has an additional component,
namely the environment. What I think we *really* want is a way to have
the name to object binding be dependent on the environment as well.
This issue is more important than the issue of user level multiple
names per class (even for metaclass programming) since it directly
affects implementations which can't use virtual memory to segment
processing steps, and could adversely affect bootstrapping in any event.
As I mentioned in a previous note, I think this issue should be resolved
by a comprehensive, well thought out statement about the processing model
for the Concepts chapter. Then, individual functions which require
interface modifications should be modified. As Patrick mentioned in his
note, the environment need not be a CLtL environment; in fact, given
the second class status of environments in Common Lisp, it is hard
to see how it *could* be without some beefing up of what you can do
with them.
I'll leave it at that for this note. Summarizing, my feeling is that
allowing a multiple name per class object binding has some serious problems
for user level code, since the names of class objects are and
probably should be settable. I don't feel offering the functionality
to users is particularly important at this time, but if people want
it, then I think restricting the name to object mapping to be one to
one on a metaclass by metaclass basis is probably the right way to go.
More important is a resolution of the name to object mapping in different
processing environments, and this should probably be done in a comprehensive
manner, including generic functions also.
Jim Kempf kempf@hplabs.hp.com
∂13-Aug-87 0928 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Name That Class
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 13 Aug 87 09:20:00 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah09181; 13 Aug 87 11:56 EDT
Received: from ti-csl by RELAY.CS.NET id ag11477; 13 Aug 87 11:49 EDT
Received: from Jenner by tilde id AA15544; Thu, 13 Aug 87 10:22:32 CDT
Message-Id: <2764855505-13956774@Jenner>
Date: Thu, 13 Aug 87 10:25:05 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Jim Kempf <kempf%hplabsz@hplabs.hp.com>
Cc: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>,
common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Name That Class
In-Reply-To: Msg of Tue, 11 Aug 87 16:01:13 pdt from Jim Kempf <kempf%hplabsz@hplabs.hp.com>
2) Inheritance lists would be no problem, since supers must be of
the same metaclass anyway.
That's not true, supers can be of other compatible metaclasses.
But, as Patrick has pointed out, the issue is more complex. The name
to class (or name to generic function) binding has an additional component,
namely the environment. What I think we *really* want is a way to have
the name to object binding be dependent on the environment as well.
This issue is more important than the issue of user level multiple
names per class (even for metaclass programming) since it directly
affects implementations which can't use virtual memory to segment
processing steps, and could adversely affect bootstrapping in any event.
As I mentioned in a previous note, I think this issue should be resolved
by a comprehensive, well thought out statement about the processing model
for the Concepts chapter. Then, individual functions which require
interface modifications should be modified. As Patrick mentioned in his
note, the environment need not be a CLtL environment; in fact, given
the second class status of environments in Common Lisp, it is hard
to see how it *could* be without some beefing up of what you can do
with them.
This is an entirely different issue from what you've been talking about.
Environments and metaclasses are orthogonal.
I'll leave it at that for this note. Summarizing, my feeling is that
allowing a multiple name per class object binding has some serious problems
for user level code, since the names of class objects are and
probably should be settable. I don't feel offering the functionality
to users is particularly important at this time, but if people want
it, then I think restricting the name to object mapping to be one to
one on a metaclass by metaclass basis is probably the right way to go.
I don't see what can be gained by having one namespace per metaclass. I think
it compromises modularity. When you list your supers in DEFCLASS, you
don't/shouldn't have to care what metaclass they belong to as long as they are
compatible with your metaclass.
Patrick.
∂17-Aug-87 2133 kempf%hplabsz@hplabs.HP.COM Environments, Naming, and CLOS (was Re: Name that Class)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 17 Aug 87 21:32:55 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 17 Aug 87 21:31:02 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 17 Aug 87 17:02:14 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 17 Aug 87 18:02:53 pdt
Message-Id: <8708180002.AA10001@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Environments, Naming, and CLOS (was Re: Name that Class)
In-Reply-To: Your message of Thu, 13 Aug 87 10:25:05 -0500.
<2764855505-13956774@Jenner>
Date: Mon, 17 Aug 87 18:02:50 MST
From: kempf%hplabsz@hplabs.HP.COM
> 2) Inheritance lists would be no problem, since supers must be of
> the same metaclass anyway.
> That's not true, supers can be of other compatible metaclasses.
I stand corrected. In the event of a name clash, some means
of disambiguating the name to class mapping would be needed.
One possiblility would be to extend the definition of "compatible"
to include "not having classes with the same name". Provided,
of course, that multiply named classes were seen to be such
an important feature that they should be included (which I
doubt).
>
>
> But, as Patrick has pointed out, the issue is more complex. The name
> to class (or name to generic function) binding has an additional component,
> namely the environment. What I think we *really* want is a way to have
> the name to object binding be dependent on the environment as well.
> This is an entirely different issue from what you've been talking about.
> Environments and metaclasses are orthogonal.
To the extent that the metaclass protocol takes into account
the processing environment, it may be possible for a particular
metaclass to do things differently in an environment from
others. For example, a metaclass supporting a language which
always resolves inheritance at compile time would need to
deal with the environment in a different way from the default
metaclass, where inheritance is resolved much later.
> I'll leave it at that for this note. Summarizing, my feeling is that
> allowing a multiple name per class object binding has some serious problems
> for user level code, since the names of class objects are and
> probably should be settable. I don't feel offering the functionality
> to users is particularly important at this time, but if people want
> it, then I think restricting the name to object mapping to be one to
> one on a metaclass by metaclass basis is probably the right way to go.
> I don't see what can be gained by having one namespace per metaclass. I thin> k>
> it compromises modularity. When you list your supers in DEFCLASS, you
> don't/shouldn't have to care what metaclass they belong to as long as they are
> compatible with your metaclass.
I agree. I can't see much use for allowing multiple names for
classes in the first place, since it requires more syntatic
machinery on the part of the programmer to indicate precisely
which class is meant in user level code. The point of the
metaclass proposal was that, if anywhere, that might be a
place where people might want to have multiple classes with
the same name. Suppose, for example, you want to have a
WINDOW class in CLOS and one in Smalltalk (or CommonObjects,
or Flavors, etc.). But Common Lisp provides packages for
seperating namespaces, and I think that's probably enough, as
long as you don't insist on exporting more than one WINDOW.
So you could have a FLAVORS::WINDOW and a SMALLTALK::WINDOW.
Personally, I think that this issue (multiple names for classes)
is a bit of a red herring. I just presented the metclass proposal
as an example of how it might make sense, but, as was pointed
out, additional machinery would be required at the syntatic
level to support it. The package system, despite its faults,
is the customary way of modularizing namespaces in Common Lisp,
and I think we should stick with that for user level code.
The issue of multiple names in different processing environments
is somewhat different. Because the package system is read time
only, and symbols map across compilation and loading into the
same package, the package system cannot be used to allow a
class of the same name to co-exist at compile time. Similarly
for methods. In order for a class or a set of classes and
their applicable methods to be compilable in the same file,
the CLOS metaclass protocol must insert enough information
into the compile time environment so that the methods can
be defined. At the extreme, the classes being compiled
could be simply be completely defined at compile time, but
this will, of course trash any existing definitions. This is
not a problem for implementations which an easily get new
virtual address spaces (modulo lengthening the time required
for compilation of a system), since most bootstrapping problems
could be solved by simply throwing away the environment and
getting a new one (there are probably some more subtle problems
here which I'm missing).
Is that a fair statement of the problem with environments
and naming?
As mentioned in previous notes, I think a section in Part I
about what CLOS needs in terms of processing environment
is important. I might add that the ANSI C standard has
about 8 pages of material on the processing environment at
the beginning. We are, of course, limited by what CLtL provides,
but I think, within that limit, we can probably be more
precise.
∂18-Aug-87 0820 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Names to Objects and Compiler-environment
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 18 Aug 87 08:20:03 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa00914; 18 Aug 87 11:18 EDT
Received: from ti-csl by RELAY.CS.NET id af11433; 18 Aug 87 11:08 EDT
Received: from dsg by tilde id AA23644; Tue, 18 Aug 87 09:44:15 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Mon, 17 Aug 87 16:14:24 CDT
Message-Id: <2765222127-2953787@Jenner>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Names to Objects and Compiler-environment
The name-to-object primitives we have in CLOS are:
Object Function Metaclass Implementation
dependent dependent
Class CLASS-NAME No Yes
Generic-function SYMBOL-FUNCTION No Yes
Method GET-METHOD Yes *
Name-to-method mapping implementation should be left to the metaclass writer
since it is tied up to the strategy of finding the applicable methods for method
discrimination and method combination. Besides name to object mapping, the
implementation provides some generic name services (source filename recording,
redefinition warnings...) that the metaclass wants/needs to use. This answers
the * sign in the above table. I believe that we need a portable interface to
those services.
Compile environment:
In order to avoid side-effecting the running environment during COMPILE-FILE,
the environment stores definitions in another namespace (compile environment).
The management of the environment(s) should be left to the implementation. All
our name-to-object functions are affected by this. We could make the
environment implicit and say that those function will return the object from the
"right environment" (SYMBOL-FUNCTION might work like that on some
implementations), but then it becomes hard to write GET-METHOD portably. I
propose that we make the environment explicit, passed as an argument to
CLASS-NAME, GET-METHOD, their SETF functions and related function such as
FIND-APPLICABLE-METHODS. I believe that CLOS should not know a whole lot about
environments so we don't require all the implementations currently supporting
compile-environment to change. Another issue is the dynamic extent of the
compile environment: The implementation control their lifetime. Their should
be a way for the implementation to signal the fact that a CLOS object no longer
needed because COMPILE-FILE is over.
Proposal(This would be part of the metaclass protocol):
1- Environment:
The implementation should provide some objects called environments. The
implementation controls their dynamic extent and their representation.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
The function (GET-RUNTIME-ENVIRONMENT) always
returns the runtime environment.
CLOS will use environment as a key into its data structures to mark an
object defined in a given environment (ie a method defined in a file
during COMPILE-FILE) or to look it up.
2- CLOS functions that must have an environment argument:
CLASS-NAMED and its SETF form,
ADD-METHOD,
GET-METHOD,
REMOVE-METHOD,
FIND-APPLICABLE-METHODS,
ENSURE-GENERIC-FUNCTION.
Questions:
Do we need to add an environment slot to STANDARD-CLASS, STANDARD-METHOD
and STANDARD-GENERIC-FUNCTION to get the environment they were defined in?
How do we provide a portable interface to those generic "name" services provided
by the implementation?
How does the implementation signal an object that it has been deleted from the
compiler environment?
The following might work but I am not sure:
ADD-TO-ENVIRONMENT OBJECT ENVIRONMENT. Tells the implementation that
the dynamic extent of OBJECT is the same as the dynamic extent of ENVIRONMENT.
DELETED-FROM-ENVIRONMENT OBJECT ENVIRONMENT this function is called by
the implementation on every object added to the environment by the call
to Add-to-environment before invalidating ENVIRONMENT. typically, It is
done at the end of COMPILE-FILE.
∂18-Aug-87 1136 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 18 Aug 87 11:35:40 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 18 Aug 87 08:51:16 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 18 Aug 87 08:50:43 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 18 Aug 87 09:51:23 pdt
Message-Id: <8708181551.AA15800@hplabsz.hpl.hp.com>
To: Kelley.pa@Xerox.COM
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of 05 Aug 87 17:48:00 -0700.
<870805-174848-5665@Xerox>
Date: Tue, 18 Aug 87 09:51:20 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry it's taken so long to respond.
>
> The CLOS proposed standard explicitly claims in general to obey the
> implicit inheritance - explicit override rule, but it does not for
I couldn't find a reference to "implicit inheritance - explicit override"
in Part 1 of the 87-002 spec. What page is it on?
> In as much as implicit inheritance is a sub-conscious assumption of
> application programmers, standard CLOS behaves in a counter intuitive
> manner.
In my opinion, inheritance should *never* be a sub-concious assumption.
It should be an explict design decision, made after considering
alternatives. If the supers are in a library to which the programmer
does not have source, then enough information should be given in the
library's documentation that the programmer can design accordingly.
Full analysis might not be required during a prototyping phase, but
nevertheless, the programmer should be familiar with the details of
the supers.
> (defclass border (object) (width))
> (defmethod close (b border) ...)
> (defclass window (object) (width))
> (defmethod close (w window) ...)
> (defclass bordered-window (border window))
> (setq b-window (make-instance 'bordered-window))
> (close b-window) ; with the current inheritance algorithm, only closes
> the border. Does not close the window.
> The following explores what could happen if the implicit inheritance -
> explicit override rule were followed in CLOS.
> (close b-window) would result in both the border and window close
> methods getting called because it inherits them implicitly and has not
> explicitly overridden them.
> With implicit inheritance a class may have in addition to multiple
> methods with the same name that all get called by one call, multiple
> occurrences of a slot with the same name that are manipulated in one
> operation so b-window would contain two slots named width.
> (setf (slot-value b-window width) 0)
> Would set both slots to 0.
Consider what would happen with a join superclass. In your example
OBJECT is a join superclass, since it is inherited through two supers
(WINDOW and BORDER) in BORDERED-WINDOW. For the supers above the join,
the base class gets two copies of slots, one through each branch through
the join class. There are two alternatives about what to do with the
two sets of slots:
1) Keep a seperate set for each branch of the join,
2) Merge them in some manner.
If the first approach is taken, then the object essentially has duplicate
copies of logically the same state. This approach was used in
CommonObjects, and is one aspect of CommonObjects which seems to bother
programmers the most. If the second approach is taken, it is possible
for some methods to be invoked more than once on the same set of
slots, making the method semantics for singly inherited and multiply
inherited cases different (see below for more discussion).
> A problem is what to do with the results of an operation on a slot name
> that refers to two or more slots or on a call that refers to two or more
> methods. Operating on these slots or methods that have not been
> overridden could be specified to return a "multiple-inheritance-result"
> object containing the multiple results.
This seems to me to be more complicated than most application programmers
will want. It would be hard to integrate with WITH-SLOTS, and would require
more syntatic machinery for setting or getting slots, pathnames to the
appropriate slot, or something similar. It seems inappropriate to
burden programmers with having to deal with such extra syntatic
machinery when slot merging will do the job most of the time.
> Any code that depended on the results from instances of singly inherited
> classes would not work correctly with instances of multiply inherited
> classes. (In the example above, any code that depended on the value
This is a general problem with linearizing multiple inheritance,
but most programmers who have used Flavors or CommonLoops are used to it,
and plan accordingly. It requires more knowledge about the supers
than for singly inherited languages, however.
The problem here is that every algorithm for multiple inheritance loses
somehow. If linearizing multiple inheritance is used, then the problem
with changing method semantics occurs. If tree-structured multiple
inheritance is used (where the entire tree of supers
is maintained, duplicating branches above joins) then duplicated state
occurs above join classes. If graph structured multiple inheritance is
used (where the graph of supers is maintained without duplication),
methods can be invoked multiple times on the same slot.
For a more detailed analysis, see Alan Snyder's paper in the last
OOPSLA proceedings.
What CLOS has tried to do (I think) is to provide Lisp programmers with
what they are most used to (i.e. codify existing practice), and to
do so in a manner which produces expected behavior most of the time.
If a programmer requires something out of the ordinary, then more time
and effort needs to be invested in learning more details, and, with
the metaclass protocol, much flexibility for changing inheritance
behavior is available. Where the CLOS inheritance algorithm could be
faulted, is that it handles the inability to linearize an inheritance
graph as an error, rather than providing hooks for the programmer
to override the default.
Alternatives to multiple inheritance for achieving the same effect
(i.e. maximum code reuse) are the subject for another basenote and
mailing list.
Jim Kempf kempf@hplabs.hp.com
∂18-Aug-87 1146 Moon@STONY-BROOK.SCRC.Symbolics.COM Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 11:45:56 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 215676; Tue 18-Aug-87 14:47:05 EDT
Date: Tue, 18 Aug 87 14:46 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Agenda for September meeting
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870818144639.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Sonya and I have put together a proposed agenda for the meeting
in September. Let's agree on what the agenda will be by the end
of this week.
Earlier I said that I wanted to leave by Friday noon, but in putting
together the agenda it became clear that 1 1/2 days wasn't enough time.
Hence we've written the agenda for two full days. Is that okay with
everyone?
Agenda for CLOS Meeting Sep 17-18 at Lucid in Menlo Park (first draft)
THURSDAY MORNING:
Discuss written proposals on major areas, circulated over the network
before the meeting and brought to the meeting in hardcopy. Spend no
more than 45 minutes on each proposal, determining yes, no, or needs
further discussion. Expected areas for proposals: object creation, new
draft of metaclass chapter, change-class, 1 or 2 others.
BREAK
Discuss a list of minor issues, to be circulated over the network before
the meeting and brought to the meeting in hardcopy. Moon will provide a
list (based on one that has already been circulated, updated from recent
mail), others will probably add to the list. Spend no more than 10
minutes on each issue, determining yes, no, or needs further discussion.
If yes, assign a volunteer to update the document accordingly.
LUNCH (let's keep this short)
Finish going through list of minor issues.
BREAK
Discuss proposals & issues that were determined to need further
discussion in the morning, in priority order. Objective is to decide
what will be in the document for the October X3J13 meeting. Things we
can't agree on here will be listed in the document as open issues.
END OF THURSDAY
Individuals may want to work on proposal drafts, writing tasks, etc.
during the evening.
FRIDAY MORNING:
Allocate remaining writing tasks and make sure we understand how we will
produce a document in time for the October X3J13 meeting, to be mailed
out around September 30. The objective should be for the tasks remaining
after the meeting breaks up to be purely editorial.
Prepare first drafts of material to go into the document, for all issues
where group effort is required. Each issue should have an individual
assigned as the leader for that issue, who writes the first draft which
is then criticized by others who are interested.
FRIDAY AFTERNOON:
Review what was written in the morning.
PREPARATION REQUIRED AHEAD OF TIME
Use network mail to finalize list of issues to be discussed and to get
everyone up to date on them.
Circulate proposals and issues list by the Friday before the meeting
(Sep 11).
Mail out hardcopies of the latest version of the 87-002 document
immediately (no further editing is planned, right?).
∂18-Aug-87 1522 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 15:22:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 215969; Tue 18-Aug-87 18:22:49 EDT
Date: Tue, 18 Aug 87 18:22 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
I would like to propose a small simplification of the short form of
define-method-combination.
Recognizing both an unqualified method and a method whose qualifier is
the name of the method combination type as primary methods seems
unnecessary and confusing. It muddles the issue of the identity of
a method (these are two separate methods with separate identities,
yet they do the same thing).
In addition, the qualifier is the name of the method combination type
but in the keyword package, so this is one more place where CLOS is
inventing symbols that don't appear in the source of the program, and
each time we do that it seems to cause trouble.
A possible drawback of this simplification is that it might make it
harder for users to understand the difference between "primary method"
and "unqualified method", since there won't be a counterexample to
the theory that the two terms are synonymous.
The specific document amendments are as follows, referring to 87-002:
2-27 Remove "A method with the keyword symbol with the same name as
{\it name\/} as its one qualifier is also defined to be a primary
method. Attaching this qualifier to a primary method documents that
this method is intended for use with an unusual form of method
combination and can make programs easier to understand."
2-30 Remove ":and" after "defmethod func".
Remove "(:and)" after "primary ()".
2-31 Remove "(:and)" after "methods ()".
Remove "(:and)" after "primary ()" [two places].
A related point is that we forgot to say in the document that a primary
method is required when using a method combination type defined with
the short form of define-method-combination, just as when using standard
method combination. We should say that explicitly.
∂18-Aug-87 1534 Kelley.pa@Xerox.COM Re: ECOOP Reaction to CLOS
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 18 Aug 87 15:34:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 18 AUG 87 15:33:17 PDT
Date: 18 Aug 87 15:31 PDT
From: Kelley.pa@Xerox.COM
Subject: Re: ECOOP Reaction to CLOS
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Tue, 18 Aug 87
09:51:20 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: Kelley.pa@Xerox.COM, common-lisp-object-system@sail.stanford.edu
Message-ID: <870818-153317-1383@Xerox>
> The CLOS proposed standard explicitly claims in general to obey the
> implicit inheritance - explicit override rule, but it does not for
|I couldn't find a reference to "implicit inheritance - explicit
override"
|in Part 1 of the 87-002 spec. What page is it on?
I was refering primarily to page 1-7, the first paragraph both under
Inheritance of Methods and Inheritance of Slots and Slot Options.
Obeying implicit inheritance in general is claimed there (though
explicit override is implicit :-). The implication that the rule was
quoted as such in 87-002 was unintentionally misleading -- one too many
explicits in my original statement.
| ... the object essentially has duplicate
|copies of logically the same state. This approach was used in
|CommonObjects, and is one aspect of CommonObjects which seems to bother
|programmers the most. ...
If inheritance of methods with the same name in CommonObjects signals an
error, that is inconsistent with its slot inheritance.
|The problem here is that every algorithm for multiple inheritance loses
|somehow. ... If tree-structured multiple
|inheritance is used (where the entire tree of supers
|is maintained, duplicating branches above joins) then duplicated state
|occurs above join classes....
Based on the arguments in Snyder's OOPSLA 86 paper, I would claim this
problem is really a feature in disguise.
At any rate, presenting the effects of the proposed inheritance
algorithm for CLOS would be more understandable if in conjunction with
presenting the class ordering algorithm, violations of the "implicit
inheritance - explicit override" rule are clearly marked as such.
-- kirk
∂18-Aug-87 1615 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 18 Aug 87 16:15:06 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110793; Tue 18-Aug-87 19:09:52 EDT
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability. I think it's hard to understand what a method is doing if
you don't know how that method is going to be combined. Having the
qualifier there reminds you what kind of combination is going to be
used.
In order to eliminate the problem of having two separate methods that do
the same thing, I would rather make use of the qualifier be required
than forbidden.
I realize that this does not solve the problem of inventing symbols.
However, I think the benefit in readability outweighs this consideration.
∂18-Aug-87 1707 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: ECOOP Reaction to CLOS
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 17:07:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216070; Tue 18-Aug-87 20:06:44 EDT
Date: Tue, 18 Aug 87 20:06 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: ECOOP Reaction to CLOS
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <8707092024.AA22131@hplabsz.hpl.hp.com>,
The message of 6 Jul 87 14:30 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Some comments on characterizing the class precedence list algorithm.
In my comments I will refer to this set of classes (slots omitted):
(defclass a (b c w)) w x w y w x
(defclass aa (b c d w)) \ / \ / \/
(defclass b (w x)) b c d w
(defclass c (w y)) \ | / /
(defclass d (w x)) \ | / /
(defclass w ()) \ |/ /
(defclass x ()) aa
(defclass y ())
We've seen these classes before. By the rules in 87-002,
the CPL of a is (a b c w y x) and of aa is (aa b c d w x y).
Date: Thu, 9 Jul 87 13:24:38 pdt
From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
The inheritance graph is searched depth first, left to
right, up to joins. Superclasses at joins are placed
in the class precedence list at the last occurance,
rather than the first, since such superclasses are
usually more general than their subclasses, and classes
at the end of the class precedence list should be more
general than those at the beginning. The qualitative
effect is to achieve a linearization of the inheritance
graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph.
A more detailed explantion should go into what can go wrong. The
Ducournau and Habib paper discusses this in a more formal way....
I like this informal way of explaining it, except that I never figured
out precisely what "up to joins" means, and depending on the
interpretation of that phrase, this explanation could be incorrect.
When the depth first walk of the graph for aa above encounters w above
c, that's a join. If it goes on to y, I don't think y is a join,
nevertheless y is not next in the CPL, x is.
Date: 06 Jul 87 1130 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
What would constitute an understandable characterization of the CPL?
Here are some examples of approaches:
1. We could have a set of constraints on the classes such that the CPL
is the unique total ordering satisfying those constraints.
If I understand the meaning of constraints as being additive, the
example above shows that it can't be done with constraints. Taking a
and adding d to make aa reverses the order of x and y, thus whatever
constraint was controlling the order of x and y must have been removed
when d was added. Perhaps this nonadditiveness is at the root of
people's difficulty in understanding the CPL computation.
2. We could have a set of inheritance situations such that when two
graphs of classes were inherited in particular ways, the new CPL was
predictable. For example, suppose we have 2 graphs, G1 and G2, with no common
classes except for the class named T and suppose that C1 and C2 are the
bottom-most classes of G1 and G2, respectively; then if a class C is
a subclass of C1 and C2 in that order, the classes in G1 precede the classes
in G2, and the classes in G1 are in the same order as they are in the CPL
for C1 and similarly for G2; T comes last.
Characterization #2 is in fact true, and it's not too hard to see why.
Suppose G1A is the second class in C1's class precedence list. After
topological sort has added C1 to C's cpl, the rule at the top of page
1-15 comes into play because either C2 or G1A could be next. The rule
selects G1A. By what amounts to induction, one can show that every
class in G1 will have a direct subclass to the right of C2's direct
subclass (C), and therefore every class in G1 will precede C2. I believe
one can also show that the classes in G1 will appear in the same order in
C's cpl as in C1's cpl. I don't think it's a coincidence that
characterization #2 is true, I think making it true was one of the
acceptance criteria for the CPL algorithm.
The problems occur just when G1 and G2 do have common classes (other
than T).
∂18-Aug-87 1728 Moon@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 18 Aug 87 17:28:19 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216083; Tue 18-Aug-87 20:29:21 EDT
Date: Tue, 18 Aug 87 20:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Names to Objects and Compiler-environment
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2765222127-2953787@Jenner>
Message-ID: <870818202904.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
I agree with the general thrust of what you're saying, but have some
nits to pick and a question to ask. I might have more to say on this
topic later.
Question: I had thought that environments referred only to the mapping
from names (Lisp symbols) to objects, but in saying that ADD-METHOD,
GET-METHOD, REMOVE-METHOD, and FIND-APPLICABLE-METHODS (not documented)
need an environment argument, I think you're saying that environments
also affect the mapping from generic-function objects to lists of
method objects. Is this correct? And is there any other kind of
mapping that they affect?
An environment of NIL should be defined to be synonymous with the
run-time environment, for programmer convenience.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
Does GET-CURRENT-ENVIRONMENT take no arguments? I believe that the
&environment argument to a macro expander is the only viable way for
the macro expander to know whether the code it's going to return has
its meaning defined in terms of the compile-environment or the run-time
environment. Thus I believe that the macro expander should pass its
&environment argument to GET-CURRENT-ENVIRONMENT. To avoid confusion,
we should either declare that these two kinds of environments are
identical, eliminating the need for GET-CURRENT-ENVIRONMENT, or else
we should find a new name for the CLOS kind of environment.
If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
some form of dynamic scoping, rather than lexical scoping, and you can
get scoping problems. Symbolics' implementation, and I believe TI's as
well, currently works this way, using the special variable
SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
environment they are working. The genesis of this is historical and
predates lexical scoping. This causes a number of subtle problems.
CLOS should not make this mistake.
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
I don't understand how adding GET-NEXT-ENVIRONMENT to the documented
interface is related to the issue of search lists. The implementation
can have those without anything special for them in the interface.
If there is searching, and I think there needs to be if only so the
compile environment can inherit from the run time environment, you need
a negative inheritance mechanism, so that the compile environment can say
such and such a method does not exist in the new version of this program
being compiled, even though it exists in the old version that is being
used to do the compilation.
How does the implementation signal an object that it has been deleted from the
compiler environment?
I would prefer that object deallocation be left to the garbage collector.
Are there any problems with that?
∂19-Aug-87 0632 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 06:32:28 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216238; Wed 19-Aug-87 09:33:33 EDT
Date: Wed, 19 Aug 87 09:32 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: DLW@ALDERAAN.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>
Message-ID: <870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Initially, I had the same opinion you state -- that having the qualifier
in the defmethod form enhances readability, and that it was preferable
to make that qualifier be required rather than forbidden.
The reason for including the qualifier in the defmethod form is to
document the method (how it will be combined with other methods). But
we already provide a way to document a method, via the documentation
string. So now I'm in favor of having the methods be unqualified
instead of requiring that they be qualified.
Either of the new suggestions would be better than the way it is now,
where you can choose whether to include the qualifier or not.
∂19-Aug-87 0745 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 19 Aug 87 07:44:55 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 110961; Wed 19-Aug-87 10:27:55 EDT
Date: Wed, 19 Aug 87 10:25 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>
Message-ID: <870819102506.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
I don't think the documentation string is adequate to produce the
results I'd like to see. In practice, I just don't believe that
programmers will, in fact, invariably (or even usually) remember to note
the method combination type in the documentation string for every method
that uses non-default method combination.
∂19-Aug-87 1020 Moon@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 10:20:10 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216470; Wed 19-Aug-87 13:21:20 EDT
Date: Wed, 19 Aug 87 13:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870818182230.3.MOON@EUPHRATES.SCRC.Symbolics.COM>,
<870818190658.2.DLW@CHICOPEE.SCRC.Symbolics.COM>,
<870819093252.6.SKEENE@JUNCO.SCRC.Symbolics.COM>,
<870819102506.5.DLW@CHICOPEE.SCRC.Symbolics.COM>
Message-ID: <870819132057.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability.
Requiring the qualifier would satisfy my stated wants, provided that the
qualifier wasn't optional (so there was only one way to write a primary
method) and wasn't re-interned in the keyword package (so we aren't
inventing symbols).
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
∂19-Aug-87 1123 skeene@STONY-BROOK.SCRC.Symbolics.COM Names to Objects and Compiler-environment
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 11:23:15 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216533; Wed 19-Aug-87 14:23:16 EDT
Date: Wed, 19 Aug 87 14:22 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Names to Objects and Compiler-environment
To: DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET
cc: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <2765222127-2953787@Jenner>
Message-ID: <870819142229.0.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
The name-to-object primitives we have in CLOS are:
Object Function Metaclass Implementation
dependent dependent
Class CLASS-NAME No Yes
Generic-function SYMBOL-FUNCTION No Yes
Method GET-METHOD Yes *
There's also GET-SETF-GENERIC-FUNCTION.
∂19-Aug-87 1349 DLW@ALDERAAN.SCRC.Symbolics.COM short form of define-method-combination
Received: from [128.81.41.109] by SAIL.STANFORD.EDU with TCP; 19 Aug 87 13:49:28 PDT
Received: from CHICOPEE.SCRC.Symbolics.COM by ALDERAAN.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 111131; Wed 19-Aug-87 16:50:17 EDT
Date: Wed, 19 Aug 87 16:47 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: Moon@STONY-BROOK.SCRC.Symbolics.COM, Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870819132057.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870819164729.8.DLW@CHICOPEE.SCRC.Symbolics.COM>
Date: Wed, 19 Aug 87 13:20 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
You seem to be setting up a hypothetical alternative, but I don't
understand what the alternative is. We don't have a language for
contracts.
It just seems to me that it's very hard to understand what a method is
doing, and easy to misunderstand it or be confused, if you don't see
what kind of combination is being employed. When you see a BEFORE
method, you know what that is. When you see an unqualified method, you
naturally assume that it's a primary method, and that (for example) what
it returns will be the result of the generic function call. But that's
not true if it's an AND-combined method, or worse yet a PROGN combined
method.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
I doubt I can come up with something much more convincing. It just
seems a lot clearer to me. (DanG mentioned to me, two days ago, that he
feels the same way.) In fact, I thought that the reason that qualifiers
for things like AND and OR were first (1980?) introduced was because we
felt they made the code clearer.
∂19-Aug-87 1455 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Names to Objects and Compiler-environment
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 19 Aug 87 14:55:12 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ae09985; 19 Aug 87 17:46 EDT
Received: from ti-csl by RELAY.CS.NET id ac19836; 19 Aug 87 17:33 EDT
Received: from Jenner by tilde id AA03684; Wed, 19 Aug 87 15:19:37 CDT
Message-Id: <2765391661-13139657@Jenner>
Date: Wed, 19 Aug 87 15:21:01 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Names to Objects and Compiler-environment
In-Reply-To: Msg of Tue, 18 Aug 87 20:29 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
Date: Tue, 18 Aug 87 20:29 EDT
From: "David A. Moon" <Moon@scrc-stony-brook.arpa>
Subject: Names to Objects and Compiler-environment
Date: Mon, 17 Aug 87 16:15:27 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
I agree with the general thrust of what you're saying, but have some
nits to pick and a question to ask. I might have more to say on this
topic later.
Question: I had thought that environments referred only to the mapping
from names (Lisp symbols) to objects, but in saying that ADD-METHOD,
GET-METHOD, REMOVE-METHOD, and FIND-APPLICABLE-METHODS (not documented)
need an environment argument, I think you're saying that environments
also affect the mapping from generic-function objects to lists of
method objects. Is this correct?
Yes, I want to do this primarily because It allows to be more efficient in terms
of structure copy. My file contains:
(defmethod speed ((thing my-ship))
.....)
;;some other things but no DEFCLASS for my-ship and
;;no DEFGENERIC-OPTIONS for speed.
During COMPILE-FILE I think it is unnecessary to copy the generic-function
or/and the class, to hold the method definition. What I had in mind was to add
the method to the runtime version of SPEED, in another namespace so a lookup for
this method in the runtime environment is not affected. I realize that we can
avoid this by copying the generic-function object to the compile environment,
but then we will have to copy some other objects (those side effected by the
defmethod) and end up having to copy a large portion of the world. Since we
tend to store first class object instead of names, we can't get enough leverage
off the name-to-object lookup. I tried to address this problem.
And is there any other kind of mapping that they affect?
I don't know, I can't think of any others but I might be ovelooking something.
An environment of NIL should be defined to be synonymous with the
run-time environment, for programmer convenience.
One can get an environment by the function GET-CURRENT-ENVIRONMENT. If
an implementation supports compile-environment, then a call to
GET-CURRENT-ENVIRONMENT in the top level loop is not EQL to a call to
GET-CURRENT-ENVIRONMENT inside a macro expansion while compiling a file.
Does GET-CURRENT-ENVIRONMENT take no arguments? I believe that the
&environment argument to a macro expander is the only viable way for
the macro expander to know whether the code it's going to return has
its meaning defined in terms of the compile-environment or the run-time
environment. Thus I believe that the macro expander should pass its
&environment argument to GET-CURRENT-ENVIRONMENT. To avoid confusion,
we should either declare that these two kinds of environments are
identical, eliminating the need for GET-CURRENT-ENVIRONMENT, or else
we should find a new name for the CLOS kind of environment.
If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
some form of dynamic scoping, rather than lexical scoping, and you can
get scoping problems. Symbolics' implementation, and I believe TI's as
well, currently works this way, using the special variable
SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
environment they are working. The genesis of this is historical and
predates lexical scoping. This causes a number of subtle problems.
CLOS should not make this mistake.
I agree with you. Passing the &environment argument to get-current-environment
is the best. I feared that the existing implementation would have to change too
much. If we do that, the compiler must tie up their compile-environment to the
macroexpand environment (which, to me, is a good thing ) and therefore must
change.
I don't think the two environments must be identical: a macroexpand
environment is free to change at each top level form, the compile environment
needs to be stay EQ for the extent of COMPILE-FILE. I would propose NAMESPACE
instead of environment.??
GET-NEXT-ENVIRONMENT ENVIRONMENT. This function returns the next
environment to lookup if any or NIL. This allows the implementation to
implement search lists.
I don't understand how adding GET-NEXT-ENVIRONMENT to the documented
interface is related to the issue of search lists. The implementation
can have those without anything special for them in the interface.
If we want a metaclass to be written portably, to use environments, and be able
to implement the searching by itself, GET-METHOD should be able to be coded
like: search the method, using the specified environment as a tag and then using
the next environment and so forth. Does that make sense? I guess it is tied to
this assumption: [From my original message: Name-to-method mapping
implementation should be left to the metaclass writer since it is tied up to the
strategy of finding the applicable methods for method discrimination and method
combination.].
If there is searching, and I think there needs to be if only so the
compile environment can inherit from the run time environment, you need
a negative inheritance mechanism, so that the compile environment can say
such and such a method does not exist in the new version of this program
being compiled, even though it exists in the old version that is being
used to do the compilation.
I agree. (REMOVE-METHOD gf .... ENV) for example has to store in the place where
the metaclass will search that the method is not to be found in the context of
ENV. Does this negative inheritance need to be specified?
How does the implementation signal an object that it has been deleted from the
compiler environment?
I would prefer that object deallocation be left to the garbage collector.
Are there any problems with that?
The problem I see is that the objects are pointed to by more than the
environment: The direct-subclasses slot of a runtime class might point to a
compile-time class. The environment itself can be hold on to: A metaclass
writer can store object on an Alist whose key is the environment. I don't think
the garbage collector will be able to get rid of those objects.
Patrick.
∂19-Aug-87 1737 Gregor.pa@Xerox.COM meeting place
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 19 Aug 87 17:37:35 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 19 AUG 87 17:36:55 PDT
Date: 19 Aug 87 17:36 PDT
From: Gregor.pa@Xerox.COM
Subject: meeting place
To: Common-Lisp-Object-System@Sail.Stanford.edu
cc: Gregor.pa@Xerox.COM
Message-ID: <870819-173655-3259@Xerox>
I just got back and haven't had a chance to really look through the
mail. The messages I thought I should try to answer right away were the
ones about meeting time and place.
Speaking for myself and Danny, we would rather have two entire days of
meetings.
Also speaking for Danny and myself, we would rather meet at PARC this
time. We met at Lucid last time, and parking and food are easier at
PARC. We can get a nice conference room in a part of the building where
we won't be bothered. I'll even try to get us one of those fancy
(Japanese) whiteboards that makes copies of what is written on it.
∂19-Aug-87 1830 Moon@STONY-BROOK.SCRC.Symbolics.COM meeting place
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 19 Aug 87 18:30:48 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 216931; Wed 19-Aug-87 21:31:58 EDT
Date: Wed, 19 Aug 87 21:31 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: meeting place
To: Common-Lisp-Object-System@Sail.Stanford.edu
In-Reply-To: <870819-173655-3259@Xerox>
Message-ID: <870819213135.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
I don't care where we meet, but if it isn't Lucid someone should tell
Jan Zubkoff, since she has been making arrangements for a room.
∂20-Aug-87 0928 Moon@STONY-BROOK.SCRC.Symbolics.COM proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Aug 87 09:28:29 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217224; Thu 20-Aug-87 12:29:36 EDT
Date: Thu, 20 Aug 87 12:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: proposed syntactic cleanups in defmethod
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870820122915.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
We've noticed some problems with the CLOS syntax for defmethod,
especially when using methods on individuals, and in response I'd like
to propose three cleanups. Note that all of these changes are purely
syntactic; that is, they only affect the readability of programs, they
don't add or remove capabilities of the language. I hope this is a
minor issue that can be dealt with quickly.
The first problem has to do with the suggested compiler warnings
mentioned on CLtL p. 160 under the IGNORE declaration. Methods often
don't use some of their parameters for anything other than making the
method applicable for certain arguments to the generic function.
Consider this example
(defmethod additional-mail-headers ((host 'xerox.com))
(declare (ignore host))
'(:line-fold "No"))
One would prefer not to have to write the (declare (ignore host)).
This almost always happens with methods on individuals, but it can
also happen with methods on classes. Consider
(defmethod color ((e elephant))
(declare (ignore e))
'grey)
I propose that the DEFMETHOD macro be specified to "refer to" (in the
sense of CLtL p.160) each specialized parameter. This means that a
compiler warning will not occur regardless of whether the body of the
method does or does not refer to the parameter, and the declare ignore
in the above examples must be removed. This makes sense intuitively
if one regards the type check of the argument against the parameter
specializer as being part of the method; thus any specialized parameter
is referred to by the type check.
An interesting effect of this is that
(defmethod part-color ((e elephant) part)
'grey)
and
(defmethod part-color ((e elephant) (part t))
'grey)
are no longer synonymous, since the first gives a compiler warning
and the second does not. I think this is a feature, not a bug.
================
The second problem relates to the use of the single quote syntax (') for
methods on individuals. There are actually two problems here. One is
that that single character is easy to overlook. One of the most common
mistakes of beginning Lisp programmers is omitting quote marks or putting
them in the wrong place. Actually, it's not only beginning programmers
who do this. I still do it myself sometimes, and I believe I have seen
Danny Bobrow do it.
I believe the programmer who intended to write
(defmethod color ((e elephant))
'grey)
but accidentally wrote
(defmethod color ((e 'elephant))
'grey)
instead is going to have a lot of trouble figuring out what happened.
It would be better to make the latter form a syntactic error, so that
we can give a clear error message. We should use a different syntax for
methods on individuals. The quote mark is a cute hack, but I think we
can afford to use something slightly more verbose. Suggestion below.
The other problem with methods on individuals is that the current syntax
is awkward when the individual is anything other than a symbol or a
number, just because defmethod is using a special magic syntax instead
of a normal Lisp form. Returning to my first example, suppose hosts are
to be represented by CLOS objects rather than symbols. Instead of
writing
(defmethod additional-mail-headers ((host 'xerox.com))
'(:line-fold "No"))
I now have to write
(defmethod additional-mail-headers ((host '(parse-host "xerox.com")))
'(:line-fold "No"))
but this doesn't work, because the form (parse-host "xerox.com")
is not in a position to be evaluated. I can write
(eval `(defmethod additional-mail-headers ((host ',(parse-host "xerox.com")))
'(:line-fold "No")))
but that's grotesque. I can also write
(defmethod additional-mail-headers ((host '#.(parse-host "xerox.com")))
'(:line-fold "No"))
which works for this case, but #. has scoping problems exposed by the
next example. Suppose we're writing methods on individual numbers, but
rather than sprinkle numbers all over the code, we use defconstant, as
good style dictates. This is boiled down from a remote-procedure-call
example.
(defconstant begin-code 1)
(defconstant end-code 2)
(defconstant integer-code 3)
(defconstant float-code 4)
(defmethod decode (stream (opcode '#.begin-code))
... begin processing a message ...)
One problem with this occurs when using compile-file. CLtL isn't very
clear on whether #. evaluates in an environment in which those
defconstants have been evaluated. It's likely that the programmer has
to play some games with eval-when to make this work. This could be
fixed by tightening up the semantics of compilation in Common Lisp, but
a worse problem is that #. does not and can not respect lexical scoping.
Suppose we had
(let ((begin-code 1))
(defmethod decode (stream (opcode '#.begin-code))
... begin processing a message ...))
There is no way the #. can see the environment created by the LET
which is still being read in at the time the #. is processed.
It seems that it would make a lot more sense to put a regular Lisp form
in the parameter-specializer-name, scoped completely normally, and let
the defmethod macro (rather than the programmer) take care of any
special mechanism needed to evaluate with respect to the proper
environment, including compile-time defconstants. Common Lisp doesn't
currently standardize all the primitives needed to write that defmethod
portably, but I think that only strengthens the argument for making
defmethod worry about those issues, instead of making every programmer
worry about them.
So I'd like to see the syntax of an individual
parameter-specializer-name changed to use a different word instead of
QUOTE, and to use a form that evaluates to the object, instead of the
object itself. The form is evaluated at the time the method is defined;
it is not evaluated each time the generic function is called. I have
two suggestions for what word to use, one based on what test is being
performed and the second based on the Common Lisp type system:
(defmethod additional-mail-headers
((host (eql (parse-host "xerox.com"))))
'(:line-fold "No"))
(defmethod additional-mail-headers
((host (member (parse-host "xerox.com"))))
'(:line-fold "No"))
I mildly prefer EQL over MEMBER, but I thought I'd open up both
suggestions for discussion. Each of these suggests an obvious
generalization, EQL to other predicates and MEMBER to multiple
individuals, and the choice might be based on which generalization we
want people to think about, even if we don't propose to implement the
generalization.
================
The final issue has to do with parameter-specializers rather than
parameter-specializer-names, using the terminology of 87-002 page 1-18.
I think that adding QUOTE as a type-specifier to Common Lisp is both
unnecessary and confusing. (Yes, I know I suggested it. I was wrong.)
Instead, the parameter-specializer for a method on an individual should
be (MEMBER object), the type-specifier that Common Lisp already defines
for this purpose. Note that there is no particular reason why the
parameter-specializer should be the same as the parameter-specializer-name;
they're already not the same for methods on classes.
∂20-Aug-87 1010 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 20 Aug 87 10:09:44 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217266; Thu 20-Aug-87 13:10:51 EDT
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870820131023.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on mail received in response to the last time I mailed this out
(two weeks ago). If anyone doesn't see their response included, or
thinks their favorite issue is missing, please let me know and I will
apologize for my error and add it. I hope that we can use this file as
part of the agenda for the September meeting. Let's try to resolve any
of these issues that can be resolved through the mail before that meeting.
Also, if I've marked an issue as agreed but you disagree, please speak up
now.
The rest of this message is the file. Page separator characters don't
seem to go through, so I have replaced each with 16 equal signs.
This file reflects Moon's understanding of the status of various CLOS issues,
concentrating on the more minor issues. The goal is to make sure that nothing
is overlooked, and especially to make sure that issues that have been brought up
and resolved are not forgotten before they get into the document. I've removed
most comments that were purely editorial comments on the document. I also
haven't tried to keep track of all the purely meta-object issues. I've edited
things to be as brief as possible.
All page references are to the 87-002 version of the CLOS document.
The file is divided into pages as follows:
0. This page of general outline
1. Documented holes in chapters 1 and 2 of 87-002
2. Things that have been already decided (but may not be in the document yet)
3. Issues with no apparent remaining disagreement
4. Small issues needing discussion
5. Issues whose status is unclear, maybe to be tabled
6. Big issues needing discussion, each on its own page
================
DOCUMENTED HOLES IN CHAPTERS 1 AND 2 OF 87-002
We publicly promised X3J13 that we would finish these holes and also have a new
draft of 87-003 by the next meeting (October).
1-5, 2-44 The initialization protocol for make-instance is not yet
specified.
1-13, 1-26, 2-14 Which Common Lisp types will have corresponding classes
is still under discussion.
Document has been updated in draft.
Need Cleanup Committee proposals for fixes to the type system.
2-7, 2-46 [The proposed extension to call-next-method has been accepted.]
This may not have been put into the document yet.
2-41, 2-48 [Perhaps we can adopt the condition signalling system now.]
================
THINGS THAT HAVE BEEN ALREADY DECIDED (BUT MAY NOT BE IN THE DOCUMENT YET)
27 May 87 call-next-method is allowed to take arguments, however it is an error
to give it arguments that would change the set of applicable methods. I think
we're saying this signals an error, and mentioning that in some simple cases the
lack of need for an error check can be proved at compile time, but in general a
run-time check is required. Specify precisely the type of error signalling.
10 June 87 The document has been updated with a discussion of how the standard
type classes are organized.
8/9/87 Gregor promised to draw a picture.
2-16 (slot-name form) is not allowed as an abbreviation
for (slot-name :initform form). People have been assuming this,
we have to document explicitly that it is not allowed.
The decision to reject (slot-name form) was made at the July meeting.
2-19 uninitialized slots should be an error to reference, not be defined
to return an unstandardized value with no error. I'm willing not to require
that it signals an error if people feel that would be an undue burden,
otherwise I prefer that reading an uninitialized slot signals an error.
In July we decided that signalling an error here should depend on the
declared safety level. Dick has proposed terminology for this.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
p2-39 Arguments: "list of t's" should be replaced by "list whose elements are
the class named t" since get-method only takes specializers, not names of
specializers.
Agreed.
2-42 make-generic-function should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-45 make-method should be deleted, redocumented as a class
that can be given to make-instance
July: Agreed
2-54 in the Amendments: Clarify that because class names and classes are
type-specifiers, they can be validly be used in THE special forms and in TYPE
declarations. We forgot this when we clarified that class objects can be used
with TYPEP and SUBTYPEP.
July: agreed
================
ISSUES WITH NO APPARENT REMAINING DISAGREEMENT
1-12 Should defclass be allowed to change the metaclass of an existing
class? Under what conditions should a subclass of standard-class have
the same properties wrt instance updating as standard class?
Gregor says the metaclass protocol includes a predicate function that controls
whether the metaclass can be changed, which depends on whether the
representations differ and existing instances might not be transformable.
Some cross-reference to this should be added to the documentation of DEFCLASS.
1-15 to 1-22 Several errors in the formal description of class precedence and
method combination, pointed out by Jim Kempf on 4 August and 27 July, need to be
corrected. These are editorial changes only, that is, they make what the
document says conform to what I believe our intent to have been.
2-35 The argument order of the setf method ought to be documented here.
In July we suggested making the new-value argument a required argument that
comes after all the other required arguments, and before the optional, rest,
and keyword arguments. It's important that this depends only on the two
lambda-lists, and not on any context such as the generic function object.
We still have defmethod-setf so that most users don't have to think about it
(only users making setf methods "directly").
The rule, carefully worded so as to work in the face of implementations with
non-standard lambda-list-keywords, is that the setf-lambda-list is inserted
into the normal lambda-list immediately after the last parameter-specifier
that precedes &optional, &rest, &key, or &aux. This is implemented by the
following function (should it be standardized as part of CLOS?):
(defun combine-setf-lambda-lists (lambda-list setf-lambda-list)
(do ((ll lambda-list (cdr ll))
(tail lambda-list))
((or (null ll) (member (car ll) '(&optional &rest &key &aux)))
(when (null ll)
(setq tail nil))
(append (ldiff lambda-list tail) setf-lambda-list tail))
(unless (member (car ll) lambda-list-keywords)
(setq tail (cdr ll)))))
What about the setf of values extension that Common Lisp provides syntactic
space for but does not currently prescribe? We're not going to allow that for
setf of generic functions.
2-50 Should we flush multiple-value-prog2, as leading to more discussion than is
warranted by its simplification of the presentation of define-method-combination?
Kempf: Yes.
2-51 It has been suggested that print-object should take a depth argument.
Moon strongly disagrees and points to the fourth bullet. I believe this issue
was discussed to death on the Common Lisp mailing list a few months or a year ago.
The point is that every single method for print-object should not have to deal
with *print-level*; that's unmodular.
Kempf raised a consistency argument (with defstruct?) but we decided
not to change print-object.
2-54 slot-missing should be documented in chapter 2
Gregor:
slot-missing is a generic function which takes three required
arguments and an optional fourth argument. The three required
arguments are the class of the object, the object and the name of the
slot. The fourth argument is the new value for the slot if
slot-missing is being called by setf of slot-value. This set of
arguments allows people to define methods on the metaclass for
handling slot-missing. For example, a low performance implementation
of dynamic slots could work this way.
(defmethod slot-missing ((class dynamic-class) obj slot
&optional (nv nvp))
(if nvp
(set-dynamic-slot obj slot nv)
(get-dynamic-slot obj slot)))
The default method on slot-missing signals an error of the same name.
Symbol-function (the user callable primitive) needs to be split from the
subprimitive for implementors that gets and sets the "real" function definition
of a symbol. This is so when a symbol's function definition is a generic
function object, the "real" definition can be something that is easier for the
implementation to call.
July: We need to say explicitly somewhere that calling symbol-function
of the name of a generic function is required to return the generic
function object, not the "real" definition.
Kempf: I don't see splitting SYMBOL-FUNCTION as an issue for the standard,
though it may be for certain implementations.
Moon: Right, the only standardization issue is making sure
SYMBOL-FUNCTION returns the generic function object, not something internal.
See earlier discussion of class-names (2-13), which affects symbol-function.
Not all of the "corrections and amendments" handed out at the March 1987
X3J13 meeting in Palo Alto have been put into the document yet. The
corrections are in but the amendments and the revised explanation of slot
inheritance are awaiting review by the group.
================
SMALL ISSUES NEEDING DISCUSSION
1-19 "... Common Lisp be modified to include the following semantics
for quote in a type specifier:
(deftype quote (object) '(member ,object)))"
Has any proposal for this been given to the cleanup committee?
Yes: ISSUE: TYPE-MEMBER-SINGLETON, Proposal TYPE-MEMBER-SINGLETON:QUOTE
It hasn't really gone through the mill yet, though.
In July Moon volunteered to make sure this happens, but in August
Moon said he didn't like it and we should use MEMBER in parameter
specializers instead.
1-24 Should we have a call-next-method? which calls such a next method
if it exists, else returns nil (rather than signalling an error?). This
seems useful rather than having to define many base methods on object.
Common Lisp reserves question mark for the user; this could be named
CALL-NEXT-METHOD-OR-NIL, or something like that.
Kempf: signalling an error is sufficient, this probably isn't needed.
In July we wondered whether there should be a way to get a list of
the remaining methods. What operations on that list should be
permitted?
- checking whether it's nil gives the desired feature
- checking its length
- doing something with list elements (presumably method objects)
- modifying the list is clearly out
- does the list have dynamic or indefinite extent?
This may be expensive enough that it can't substitute for
CALL-NEXT-METHOD-OR-NIL.
I think we're awaiting proposals on these two issues, as well as a
concensus on whether we need these features.
2-30: Note the third paragraph on p.2-30 of 87-002, speaking of signalling an
error when the arbitrary order of two methods affects the result. I suggest
that this error be mandatory instead of optional.
2-38 need a way to recover documentation of a method-combination type
July: do this by adding a new value for the second argument to DOCUMENTATION.
But the whole writeup on DOCUMENTATION is screwy, and we need a new proposal.
When the CL-Cleanup subcommittee finishes cleaning up the concept of
"definition" (I think it's waiting for Masinter to propose something)
then DOCUMENTATION should follow.
2-57 What does with-slots do for slots that exist in the class but don't
have accessors, when :use-accessors t is specified (or defaulted)?
July: it shadows any outer bindings of the slot name, and if you
actually access that pseudo-variable, it signals an error.
Gregor: What if by the time you actually run the body of the method, the slot
has an accessor? It all hinges on exactly when macro-expansion time is and
that is not specified.
There are two issues here:
(1) Exactly when is the set of names scoped with with-slots determined?
(2) Exactly when is the presence or absence of an accessor for a name
determined?
What can be done with method objects, e.g. can one method be added
to more than one generic function?
Kempf: There may be a problem if the method invokes CALL-NEXT-METHOD.
[I wasn't able to understand his description of the problem -- Moon]
Gregor: I believe it should signal an error to attempt to put a method on more
than one generic function. My model of this is that if you want to do
something like that, you can take one function, use it as the method function
of multiple methods, each of which would be on a different generic function.
I'm not sure if we said anywhere what happens when you call a generic
function and there is no applicable method; I think it ought to signal
an error.
Gregor:
This is a generic function like slot-missing. There is a generic
function NO-MATCHING-METHOD which is called with the generic function
as the first argument and the arguments to the generic function as
the remaining arguments. This allows people to define a method to
handle the no matching method case either on the class of the generic
function or on the individual generic function. The default method
for no-matching-method signals an error of the same type.
The error message should give some information about
the classes of the parameters, to help debugging.
CALL-NEXT-METHOD with no more methods should do something similar,
but not identical.
funcallable-standard-class should be documented. It is a metaclass.
This is what makes generic function objects funcallable. There is a slot
that is the actual function that gets called.
I think Gregor volunteered to propose details.
We need to decide whether class-name of an anonymous class is nil or
signals an error.
The concensus seems to be to return nil.
What does type-of return when applied to an instance of an anonymous
class?
Returning NIL is not valid by CLtL's definition of TYPE-OF.
The choices are either to return the class object itself or
the name of some superclass that has a name, T if necessary.
================
ISSUES WHOSE STATUS IS UNCLEAR, MAYBE TO BE TABLED
1-17 "It is currently under discussion whether to provide constructs
for giving generic functions local names." Do we want to have this
discussion, or to punt on this syntax. I recall we did come up with some
reasonable semantics for a GFLET and GFLABELS.
In July we decided to defer this.
2 Aug 87 RPG offered to write a proposal.
2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
2-46 Last line: If call-next method is extended ..." I see no reason
for additional keyword arguments.
Moon doesn't remember the issue. It may have been consistency; if call-next-method
can specify the arguments, then so can make-method-call. You need one keyword
argument to specify the methods and another to specify funcall versus apply.
It could also have been that call-next-method would be implemented in terms of
make-method-call, and therefore would need to be able to specify the arguments.
2-6 call-next-method dynamic versus indefinite extent
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
Gregor: I am pretty sure what we meant was we didn't want to have to worry
about the case where someone returns a closure that includes a call
to call-next-method, and then redefines the class or method structure
so that the closure would have to call different 'next methods'.
Moon: Oh, so this is different from extent, because they could do that
redefinition before the method returns. So either we should say it
captures the set of next methods at a particular instant, or it's
undefined what happens if you redefine.
2-9 semantic difficulties discussion was shortened for the document so much
that much of the point was lost. At some point we need to decide how much
we want to standardize about this and where we want to say it; in the main
standard or in some kind of implementation guide.
[no response to this so far, Moon should propose I guess]
2-16 boa-arglist should support &key and &allow-other-keys.
2-18 default boa-arglist to be specified
Status depends on whether object-creation proposal includes constructors.
Moon: method arglist congruence still doesn't satisfy me. I have some
ideas about this but unfortunately have not managed to pull them together.
To be resolved as part of the initialization protocol discussion.
Which symbols defined by the standard go in what package?
July: I think we said some will go in LISP: and some will go in CLOS: and
we don't know yet where to draw the line.
The top level macros and functions should be part of LISP.
The internal functions specified for the sake of metaclass programming
can reside in CLOS.
If CLOS is an optional part of CL, are the symbols in the LISP package
even when the option is not present? Probably.
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the ordering
of classes that only apply conditionally, i.e. if those classes are
actually present among the superclasses. He considers this bad style.
Moon volunteered to write a proposal with some examples, and we agreed
to resolve this over the mail.
================
PREFIXED SYMBOL NAMES
These two issues appear to be related.
2-18 (:accessor-prefix nil) is not a good way to say "use the slot names
as the accessor names". We need to fix this.
We could add another option, or remove the whole prefix feature, and
require accessor names always to be listed explicitly.
In July we agreed to discuss this in the mail.
2-57 with-slots :prefix package problem; This was discussed in the mail and
then the ball was dropped. What's in the document is unworkable because it
depends on the dynamic value of *package* at macro-expansion time, but Common
Lisp doesn't guarantee anything about when macro-expansion occurs. Moon would
prefer to flush the :prefix option. An alternative that was discussed was to
use symbol-package of the prefix, both here and in defclass accessor construction,
as the package, relying on the likelihood of prefixes always ending in delimiter
characters and exported symbols never ending in delimiter characters.
July: We agreed to resolve this in the mail.
Kempf, Moon: Flush :prefix.
Gregor: I like the prefix option, although I agree that this is a serious
problem.
================
ENSURE-GENERIC-FUNCTION
A constellation of issues surrounding the mapping from generic function
names to generic function objects. This seems to be awaiting a proposal
to pull it all together.
1-18, 2-40 It is not specified whether get-setf-generic-function is setf-able.
Gregor: make it setf'able, it's just like symbol-function. Maybe
rename it to symbol-setf-generic-function?
Moon thinks this would be okay provided it is understood as setting the
mapping from a name to a generic function, not side-effecting the
generic function. See class-name discussion below (2-13).
Good reason to rename it to symbol-setf-generic-function.
This set off a discussion of how TRACE should work that maybe doesn't
bear directly on CLOS. Kempf is working on a proposal.
2-40 get-setf-generic-function needs an errorp, but it and get-generic-function
should be subsumed by ensure-generic-function which would do all the right things.
Gregor:
I propose that we keep get-setf-generic-function, but that we rename it to
symbol-setf-generic-function. In addition, I propose that we do the
following:
ensure-generic-function, add-named-method and any other CLOS
function that takes the name of a generic function as an argument
can also take a list like (SETF <symbol>) which means the
setf-generic function for that argument.
I propose that ensure-generic-function do basically what
defgeneric-options and defgeneric-options-setf used to do except that
ensure-generic-function would be a function (that is it would
evaluate its arguments). This isn't a problem since
defgeneric-options didn't take any &body arguments anyways. The real
thing that needs to be worked out here is what happens if the generic
function already exists, but is different in some ways than the
description in the arguments to ensure-generic-function.
The relevant options (referring to 2-42) seem to be:
:lambda-list -- method congruence issue
:generic-function-class -- covered below
:method-class -- are existing methods mutated?
Moon doesn't see any problem with changing these options:
:argument-precedence-order
:declare
:documentation
:method-combination
Gregor's e-g-f proposal, recovered from mail sent back in February,
and edited only slightly:
ensure-generic-function <symbol>
&key (generic-function-class
(class-named 'standard-generic-function))
(make-existing-function-default-p nil)
If symbol is fboundp to a generic-function of the same class as
generic-function-class then this function does nothing, and
returns the generic function object.
If symbol is fboundp to a generic-function of some other class, the
generic-function class changing protocol is followed, see chapter 3.
Use (class-named 'generic-function) to prevent changing the class
(is this right? does "of class" here mean typep or eq type-of?)
If symbol not foundp a generic function of generic-function-class is
created and put in symbol's function cell. There was some contention
over whether there should be a create-p argument to control this, or
the caller should do an fboundp test first.
If symbol is fboundp to a function, and make-existing-function-default-p
is not nil, a generic-function is created, put in the function cell, a
default method is added to the generic-function and the symbol's
previous function cell value is used as the function for the default
method.
If symbol is fboundp to a function and make-existing-function-default-p
is nil an error is signalled.
If symbol names a macro or a special form, an error is signalled.
Thus if this does not signal an error, it returns a generic function
object that is now the function definition of the symbol.
<symbol> can also be (setf <symbol>), as proposed later. How does the
caller do an fboundp test of this?
Feel free to change the names of the arguments. Note that this is a
function not a generic-function.
This needs to take additional arguments corresponding to all of the
arguments of defgeneric-options; see make-generic-function on 2-42.
================
CLASS NAMING ISSUE
[I have not yet summarized all the mail on this topic]
================
CLASS REDEFINITION
[I have not yet summarized all the mail on this topic]
================
COMPILER OPTIMIZATION
Kempf 29 Jul 87: There was no mention made of compile time optimization,
which I believe I made some initial proposals on in late April or early May.
I've been meaning to revisit them.
∂20-Aug-87 1525 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 20 Aug 87 15:18:52 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 20 Aug 87 13:23:58 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 20 Aug 87 13:22:33 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 20 Aug 87 14:23:19 pdt
Message-Id: <8708202023.AA19448@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Agenda for September meeting
In-Reply-To: Your message of Tue, 18 Aug 87 14:46:00 -0400.
<870818144639.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 14:23:16 MST
From: kempf%hplabsz@hplabs.HP.COM
> Earlier I said that I wanted to leave by Friday noon, but in putting
> together the agenda it became clear that 1 1/2 days wasn't enough time.
> Hence we've written the agenda for two full days. Is that okay with
> everyone?
Yes, this is fine.
> Discuss written proposals on major areas, circulated over the network
> before the meeting and brought to the meeting in hardcopy. Spend no
> more than 45 minutes on each proposal, determining yes, no, or needs
> further discussion. Expected areas for proposals: object creation, new
> draft of metaclass chapter, change-class, 1 or 2 others.
I'd like to put in debugging support under the "1 or 2 others" if nobody
has any strong objections. I'll rewrite the proposal based on the comments
Dave sent and resubmit to the network within the next week. The reason is,
our developers seem to need it.
> Mail out hardcopies of the latest version of the 87-002 document
> immediately (no further editing is planned, right?).
Yes, this is very definitely needed, as soon as possible.
-------------------------------------------------------------------------------
The rest of the agenda looks good to me. I have no particular preference
about where the meeting is held, just as long as the location is mailed
out ahead of time, so I can get there on time.
With regard to the spec documentation, I'd like to put in a vote for an ASCII
version to go on parcvax, along with the portable source, so people don't
have to be working in the dark with it. The ASCII version doesn't
necessarily have to be up to the current level of discussion and
decision within the committee (indeed, it probably shouldn't) but should
reflect approximately what is implemented. If there is some problem with
deTeXing it, we have some OCR software here which I'd be willing to give
a try at scanning it in with. Alternatively, Linda and Dick's paper from
ECOOP would be a possible source, although it's more of an overview (and
looks like it would probably be easier to scan in).
jak
∂21-Aug-87 0828 kempf%hplabsz@hplabs.HP.COM Re: proposed syntactic cleanups in defmethod
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 21 Aug 87 08:25:55 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Fri, 21 Aug 87 08:21:12 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Fri, 21 Aug 87 08:20:38 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Fri, 21 Aug 87 09:21:22 pdt
Message-Id: <8708211521.AA25991@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: proposed syntactic cleanups in defmethod
In-Reply-To: Your message of Thu, 20 Aug 87 12:29:00 -0400.
<870820122915.2.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 21 Aug 87 09:21:19 MST
From: kempf%hplabsz@hplabs.HP.COM
Proposal 1:
> I propose that the DEFMETHOD macro be specified to "refer to" (in the
> sense of CLtL p.160) each specialized parameter. This means that a
> compiler warning will not occur regardless of whether the body of the
> method does or does not refer to the parameter,
I support this proposal. I think a good case was made for it.
Proposal 2:
> So I'd like to see the syntax of an individual
> parameter-specializer-name changed to use a different word instead of
> QUOTE, and to use a form that evaluates to the object, instead of the
> object itself. The form is evaluated at the time the method is defined;
> it is not evaluated each time the generic function is called. I have
> two suggestions for what word to use, one based on what test is being
> performed and the second based on the Common Lisp type system:
I feel vaguely uneasy about this proposal. Part of the reason is because,
as rpg more forcefully stated somewhat earlier, I do not much like the idea
of having quoted objects as specializers in the first place.
The reason for this is as follows. One could view quoted objects as being
a kind of restricted subrange type. Allowing quoted objects means that users
can define methods which discriminate on individual FIXNUMs or arrays, but
disallowing subranges means they can't define methods which discriminate on
all FIXNUMs or arrays of a particular size.
One could argue that this is rather an argument for allowing subranges than for
disallowing quoted objects, but I believe that subranges are a distinctly
different kind of thing. In fact, subranges are a kind of type
parameterization, since certain parameters must be supplied at the time the
type is instantiated (as opposed to when an instance is created) and these
parameters are usually of a nature which constrain instances in some manner.
Following through on the FIXNUM example, FIXNUMs can be viewed as an
instance of a more general type, RESTRICTED-INTEGER, which requires a
parameter indicating upper and lower bounds on the size of instances.
Similarly, an individual FIXNUM can be viewed as a member of the type (EQL x).
That said, I think Moon's ADDITIONAL-MAIL-HEADER example:
> (defmethod additional-mail-headers ((host 'xerox.com))
> '(:line-fold "No"))
indicates how quoted objects as specifiers might be useful. But one could
just as well write:
(defmethod additional-mail-headers ((host symbol))
(case host
.... ;;various other possibilites
( 'xerox.com '(:line-fold "No") )))
Embedded CASE statements suffer the disadvantage that, when changes are
made (for example, adding a new host), then an additional branch must
be added or deleted everywhere. But, with quoted objects as parameter
specifiers, adding an additional case requires adding new method
definitions anyway, so I have trouble seeing any gain as opposed to the
loss of consistency cited above.
Classes could be used to generalize the mail example:
(defclass host-name ()
(
(name
:type symbol
:accessor NIL
:initform NIL
)
)
(:reader-prefix NIL))
(defmethod print-object ((object host-name) stream)
(print (name object) stream))
;;;Various other methods for dealing with host names
(defmethod additional-mail-headers ((host host-name))
(case (name host)
.... ;;various other possibilites
( 'xerox.com '(:line-fold "No") )))
Modifications to the host tables would still require adding another branch
to all CASEs, but methods operating on instances of HOST-NAME are likely
to be grouped together, and thus the difference between modifying a CASE
and adding an additional method is not large. After all, I don't think the
point of CLOS was to completely eliminate the need for CASE statements, but
rather to provide users a way of constructing code with generalizes
behaviors and structures.
So I'd actually prefer to eliminate quoted objects entirely.
> I mildly prefer EQL over MEMBER, but I thought I'd open up both
> suggestions for discussion. Each of these suggests an obvious
> generalization, EQL to other predicates and MEMBER to multiple
> individuals, and the choice might be based on which generalization we
> want people to think about, even if we don't propose to implement the
> generalization.
If the above arguments don't sound convincing, or people just don't have
the energy and want to stick with what we already have, then I'd prefer
introducing some kind of new symbol, rather than using either of these.
The reason is because I'd rather avoid having people generalize, since
either of the generalizations lead in directions which I don't think
we're prepared to address. Something like SINGELTON would be a possibility:
(defmethod additional-mail-headers ((host (singleton (parse-host "xerox.com"))))
'(:line-fold "No"))
Proposal 3:
> The final issue has to do with parameter-specializers rather than
> parameter-specializer-names, using the terminology of 87-002 page 1-18.
> I think that adding QUOTE as a type-specifier to Common Lisp is both
> unnecessary and confusing. (Yes, I know I suggested it. I was wrong.)
I agree with this (modulo my misgivings about quoted objects as
specializers in the first place); however, again I think that some specific
other symbol (like SINGLETON) would be more appropriate.
∂22-Aug-87 0004 Masinter.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Aug 87 00:04:41 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 AUG 87 00:04:47 PDT
Date: 22 Aug 87 00:04 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Fri, 21 Aug 87
09:21:19 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870822-000447-6288@Xerox>
To clarify, are you proposing that:
(dolist (x *broken-mail-hosts*)
(defmethod additional-mail-headers ((host (singleton (parse-host
x))) '(:line-fold "No")))
be a reasonable way to assign individual methods to, say, a large number
of individuals?
Implementations will have to be careful to allow objects which have
individual methods to be GCd, won't they?
∂22-Aug-87 0033 Masinter.pa@Xerox.COM Re: TRACE Proposal (Version 1)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 22 Aug 87 00:33:20 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 22 AUG 87 00:32:02 PDT
Date: 22 Aug 87 00:31 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: TRACE Proposal (Version 1)
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Mon, 10 Aug 87
11:45:31 MST
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870822-003202-6311@Xerox>
I've managed to convince myself that definition types (which are
primarily for the use of DOCUMENTATION, and a general, programmatic way
of "undoing" a DEFmumble), are pretty much independent of "function
specs", which are handles on ways of getting at things which might have
breakpoints or tracepoints associated with them.
What I'm saying is that you should go ahead with your proposal for
function-specs in trace/break without worrying about any conflict from
the definition-type proposal which I have not finished writing.
∂22-Aug-87 1837 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 22 Aug 87 18:37:38 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 218771; Sat 22-Aug-87 21:38:25 EDT
Date: Sat, 22 Aug 87 21:37 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: proposed syntactic cleanups in defmethod
To: Masinter.pa@Xerox.COM
cc: kempf%hplabsz@hplabs.HP.COM, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870822-000447-6288@Xerox>
Message-ID: <870822213731.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Line-fold: No
Date: 22 Aug 87 00:04 PDT
From: Masinter.pa@Xerox.COM
To clarify, are you proposing that:
(dolist (x *broken-mail-hosts*)
(defmethod additional-mail-headers
((host (singleton (parse-host x))))
'(:line-fold "No")))
be a reasonable way to assign individual methods to, say, a large number
of individuals?
Yes.
Implementations will have to be careful to allow objects which have
individual methods to be GCd, won't they?
Not my department. Any form of individual methods has this problem.
∂24-Aug-87 1146 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 24 Aug 87 11:46:12 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 24 Aug 87 11:41:54 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 24 Aug 87 11:41:21 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 24 Aug 87 12:42:06 pdt
Message-Id: <8708241842.AA11723@hplabsz.hpl.hp.com>
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of Tue, 18 Aug 87 20:06:00 -0400.
<870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 24 Aug 87 12:42:03 MST
From: kempf%hplabsz@hplabs.HP.COM
In <870818-153317-1383@Xerox> kirk writes:
>At any rate, presenting the effects of the proposed inheritance
>algorithm for CLOS would be more understandable if in conjunction with
>presenting the class ordering algorithm, violations of the "implicit
>inheritance - explicit override" rule are clearly marked as such.
Yes, the description in Part 1 of the spec should contain proper
documentation of how slot and class options are default inherited.
In <870818200622.4.MOON@EUPHRATES.SCRC.Symbolics.COM> Moon writes:
> Some comments on characterizing the class precedence list algorithm.
> In my comments I will refer to this set of classes (slots omitted):
> (defclass a (b c w)) w x w y w x
> (defclass aa (b c d w)) \ / \ / \/
> (defclass b (w x)) b c d w
> (defclass c (w y)) \ | / /
> (defclass d (w x)) \ | / /
> (defclass w ()) \ |/ /
> (defclass x ()) aa
> (defclass y ())
The class a seems to be missing from the diagram, but I'll refrain
from trying to include it, since the result is more confusing that
enlightening.
> We've seen these classes before. By the rules in 87-002,
> the CPL of a is (a b c w y x) and of aa is (aa b c d w x y).
> Date: Thu, 9 Jul 87 13:24:38 pdt
> From: Jim Kempf <kempf%hplabsz@hplabs.HP.COM>
> The inheritance graph is searched depth first, left to
> right, up to joins. Superclasses at joins are placed
> in the class precedence list at the last occurance,
> rather than the first, since such superclasses are
> usually more general than their subclasses, and classes
> at the end of the class precedence list should be more
> general than those at the beginning. The qualitative
> effect is to achieve a linearization of the inheritance
> graph, with more specialized classes at the head of
> the class precedence list and more general classes at
> the tail, keeping together groups of classes which occur
> together in the inheritance graph.
> I like this informal way of explaining it, except that I never figured
> out precisely what "up to joins" means, and depending on the
> interpretation of that phrase, this explanation could be incorrect.
> When the depth first walk of the graph for aa above encounters w above
> c, that's a join. If it goes on to y, I don't think y is a join,
> nevertheless y is not next in the CPL, x is.
w is, indeed, a join class, since there is more than one line
of inheritance coming out of it. The definition of a join I had in
mind is a class which contributes two or more subclasses to the
CPL calculation. y is not a join, because there is only one line of
inheritance coming from it (namely y->c->aa). x is also a join, because
there are two lines of inheritance coming from it (namely x->b->aa
and x->d->aa). If we follow the explanation, then, after including
w, we use the local precedence ordering to select x as the next
class to include. In this case, the local precedence ordering takes
priority over other rules and x is included. y is then included after
x.
So a more accurate statement would be:
Define a join class as a superclass which contributes
two or more subclasses to a CPL calculation. Define
the base class as the class for which the CPL calculation
is being made. To calculate the CPL, the inheritance graph
is searched depth first, left to right, up to joins, starting
with the base class. Join superclasses are placed in the class
precedence list at the last occurance, rather than the first,
since such superclasses are usually more general than their
subclasses (from the base class's point of view),
and classes at the end of the class precedence list should be more
general than those at the beginning. After a join class has
been inserted, the local precedence ordering for the join
class is used to start the left to right search again above
the join. The qualitative effect is to achieve a linearization
of the inheritance graph, with more specialized classes at the head of
the class precedence list and more general classes at
the tail, keeping together groups of classes which occur
together in the inheritance graph (i.e. maintaining local
precedence).
This a a bit more complicated than the original, but more accurate,
I think. Some words about failures to linearize and an example would
also be helpful.
∂24-Aug-87 1254 LGD updated spec on SAIL
To: common-lisp-object-system@SAIL.STANFORD.EDU
I have made a few minor edits to the drafts of the concepts and functions
chapters that Sonya put out on SAIL last month. The only changes of note
here are some corrections to the new standard-type-class/superclasses
table in the section "Integrating Types and Classes."
I also tweaked the macros file so that it now prints "Draft" and the date,
so that we can keep our hardcopy drafts straight while we work.
There are also new .dvi files available.
--lgd
∂24-Aug-87 1304 kempf%hplabsz@hplabs.HP.COM Re: ECOOP Reaction to CLOS
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 24 Aug 87 13:04:27 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 24 Aug 87 13:04:04 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 24 Aug 87 13:03:41 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 24 Aug 87 14:04:22 pdt
Message-Id: <8708242004.AA12343@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: ECOOP Reaction to CLOS
In-Reply-To: Your message of Mon, 24 Aug 87 12:42:03 -0700.
<8708241842.AA11723@hplabsz.hpl.hp.com>
Date: Mon, 24 Aug 87 14:04:19 MST
From: kempf%hplabsz@hplabs.HP.COM
> Define a join class as a superclass which contributes
> two or more subclasses to a CPL calculation. Define
> the base class as the class for which the CPL calculation
> is being made. To calculate the CPL, the inheritance graph
> is searched depth first, left to right, up to joins, starting
> with the base class. Join superclasses are placed in the class
> precedence list at the last occurance, rather than the first,
> since such superclasses are usually more general than their
> subclasses (from the base class's point of view),
> and classes at the end of the class precedence list should be more
> general than those at the beginning. After a join class has
> been inserted, the local precedence ordering for the join
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
> class is used to start the left to right search again above
↑↑↑↑↑
> the join. The qualitative effect is to achieve a linearization
> of the inheritance graph, with more specialized classes at the head of
> the class precedence list and more general classes at
> the tail, keeping together groups of classes which occur
> together in the inheritance graph (i.e. maintaining local
> precedence).
After I mailed this I realized that the ↑ underscored section should read:
the local precedence ordering for the join class's leftmost occuring
subclass
So integrating, and making a couple of other minor changes, gives:
Define a join class as a superclass which contributes
two or more subclasses to a CPL calculation. Define
the base class as the class for which the CPL calculation
is being made. To calculate the CPL, the inheritance graph
is searched depth first, left to right, up to joins, starting
with the base class. Join superclasses are placed in the class
precedence list at the last (rightmost) occurance, rather than
the first (leftmost), since such superclasses are usually more
general than their subclasses (from the base class's point of view),
and classes at the end of the class precedence list should be more
general than those at the beginning. After a join class has
been inserted, the local precedence ordering from the first
(leftmost) subclass of the join class is used to start the
left to right search again above the join. The qualitative effect
is to achieve a linearization of the inheritance graph, with
more specialized classes at the head of the class precedence list
and more general classes at the tail, keeping together groups of
classes which occur together in the inheritance graph
(i.e. maintaining local precedence).
∂24-Aug-87 1644 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: proposed syntactic cleanups in defmethod
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Aug 87 16:44:29 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa02900; 24 Aug 87 19:45 EDT
Received: from ti-csl by RELAY.CS.NET id ag16441; 24 Aug 87 19:34 EDT
Received: from Jenner by tilde id AA27526; Mon, 24 Aug 87 15:17:23 CDT
Message-Id: <2765823344-1583937@Jenner>
Date: Mon, 24 Aug 87 15:15:44 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: proposed syntactic cleanups in defmethod
In-Reply-To: Msg of Thu, 20 Aug 87 12:29 EDT from "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
I propose that the DEFMETHOD macro be specified to "refer to" (in the
sense of CLtL p.160) each specialized parameter. This means that a
compiler warning will not occur regardless of whether the body of the
method does or does not refer to the parameter, and the declare ignore
in the above examples must be removed. This makes sense intuitively
if one regards the type check of the argument against the parameter
specializer as being part of the method; thus any specialized parameter
is referred to by the type check.
Sounds good.
So I'd like to see the syntax of an individual
parameter-specializer-name changed to use a different word instead of
QUOTE, and to use a form that evaluates to the object, instead of the
object itself. The form is evaluated at the time the method is defined;
it is not evaluated each time the generic function is called.
I think it is a very good idea.
I mildly prefer EQL over MEMBER, but I thought I'd open up both
suggestions for discussion. Each of these suggests an obvious
generalization, EQL to other predicates and MEMBER to multiple
individuals, and the choice might be based on which generalization we
want people to think about, even if we don't propose to implement the
generalization.
I don't like MEMBER because it looks too much like the CLtL type
specifier and lots of people will think that they can discriminate on
multiple individuals. I am neutral on EQL versus another name as Kempf
suggested.
Patrick.
∂24-Aug-87 1701 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: short form of define-method-combination
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 24 Aug 87 17:01:33 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aj02900; 24 Aug 87 19:46 EDT
Received: from ti-csl by RELAY.CS.NET id ao16441; 24 Aug 87 19:36 EDT
Received: from Jenner by tilde id AA28861; Mon, 24 Aug 87 16:18:11 CDT
Message-Id: <2765827013-1804390@Jenner>
Date: Mon, 24 Aug 87 16:16:53 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: short form of define-method-combination
In-Reply-To: Msg of Wed, 19 Aug 87 13:20 EDT from "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Date: Wed, 19 Aug 87 13:20 EDT
From: "David A. Moon" <Moon@SCRC-STONY-BROOK.ARPA>
Subject: short form of define-method-combination
Date: Tue, 18 Aug 87 19:06 EDT
From: Daniel L. Weinreb <DLW@ALDERAAN.SCRC.Symbolics.COM>
I am not enthusiastic about this proposal. I have always liked having
the qualifier in the defmethod form explicitly, because it enhances
readability.
Requiring the qualifier would satisfy my stated wants, provided that the
qualifier wasn't optional (so there was only one way to write a primary
method) and wasn't re-interned in the keyword package (so we aren't
inventing symbols).
However, I don't understand why you think the method-combination type of
a generic function needs to be repeated in the defmethod, while the rest
of the contract of the generic function does not need to be repeated.
It seems to me that the command provided by the programming environment
to remind one of the arguments expected, values returned, and documentation
of the generic function can also remind one of the method-combination type.
If you convince me that the method-combination type deserves special
treatment, then I'll change my proposal to make the qualifier mandatory
instead of prohibited.
The fact that we have two ways of defining primary methods for flavors
is a major source of confusion. I got lots of questions about it. I am
glad that David Proposes to rectify things. I would be in favor of
omitting the qualifier, but if Dan objects to it, then requiring the
qualifier is OK too. To me, the important thing is that the primary
methods have all the same syntax and that we don't end up with two
primary methods for one set of specializers.
Patrick.
∂26-Aug-87 1916 Gregor.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 26 Aug 87 19:16:01 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 26 AUG 87 19:15:44 PDT
Date: 26 Aug 87 19:15 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 20 Aug 87 12:29 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870826-191544-1414@Xerox>
I have certainly been bothered by the same problems with defmethod
syntax you address, but I am not sure about all of these solutions. What
is bothering me is that while they all provide convenience, they make
the defmethod form itself more complicated. I haven't yet made my mind
up, but I thought I would send out a message to at least say something,
since you said you hoped it could be resolved quickly.
The proposal to make defmethod forms, which actually name specializers
for arguments, refer to those arguments certainly would be convenient.
There are a lot of cases in PCL code where I could remove declare
ignores. But it makes the defmethod story more complicated.
Particularly, if arguments which are not specialized are also refered
to. I am not sure this is worth the tradeoff? But I am not sure it
isn't either.
The second proposal (to evaluate the argument to an EQL or ' specializer
at load time) addresses a much more real problem. In paricular, without
this, its not possible to use call-next-method inside of methods on
individuals. That probably makes this worth doing, even it it makes the
defmethod story more complex.
I have no particular opinion on the third proposal.
I would like there to be a simple, clean story which can be used to
correspondence between any given defmethod form, and a call to
add-method, make-instance and ensure-generic-function. Thats what makes
defmethod nice syntax for add-method the same way defun is nice syntax
for setf of symbol-function.
∂26-Aug-87 2033 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: proposed syntactic cleanups in defmethod
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 26 Aug 87 20:33:36 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 221804; Wed 26-Aug-87 23:34:54 EDT
Date: Wed, 26 Aug 87 23:34 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: proposed syntactic cleanups in defmethod
To: Common-Lisp-Object-System@sail.stanford.edu
In-Reply-To: <870826-191544-1414@Xerox>
Message-ID: <870826233424.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 26 Aug 87 19:15 PDT
From: Gregor.pa@Xerox.COM
I would like there to be a simple, clean story which can be used to
correspondence between any given defmethod form, and a call to
add-method, make-instance and ensure-generic-function. Thats what makes
defmethod nice syntax for add-method the same way defun is nice syntax
for setf of symbol-function.
I agree that this is desirable. I don't think the changes I proposed make
the story more or less complicated than it was before. For example,
evaluating the specification of an individual rather than quoting it only
shows up as evaluating or quoting a particular position in the form resulting
from expansion of defmethod, I would expect.
Since I'm not sure I understand how these meta-level functions are intended
to be used, and since I have never seen the simple clean story written down,
I don't think I am competent to write out the details of how the expansion
of defmethod would be affected by my proposed changes. Gregor, perhaps you
could take a crack at it?
∂27-Aug-87 0952 kempf%hplabsz@hplabs.HP.COM Solutions to Name/Object Mapping for Generic Functions
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 27 Aug 87 09:52:00 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 27 Aug 87 09:51:04 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 27 Aug 87 09:50:38 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 27 Aug 87 10:51:23 pdt
Message-Id: <8708271651.AA07090@hplabsz.hpl.hp.com>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Solutions to Name/Object Mapping for Generic Functions
X-Mailer: mh6.5
Date: Thu, 27 Aug 87 10:51:21 MST
From: kempf%hplabsz@hplabs.HP.COM
Sorry this note has dragged on so long, but the name to object mapping
is a difficult enough problem that I think it requires some thought.
THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
As my previous note outlined, the problem with making SYMBOL-FUNCTION
sensitive to the environment is that it directly conflicts with the
Common Lisp notion of the symbol's function cell as a global place.
On the other hand, the consequences for CLOS of not somehow making
the metaclass protocol for generic functions sensitive to the environment
are that support for resolving method inheritance at compile time
will not be available in a portable way (it may and probably will be
available in an implementation dependent way, since optimizations
will require it).
A good solution should somehow avoid either of these extremes. In
addition, the solution should not be such that compilation of a
method causes redefinition of anything funcallable in the compiler's
run time environment, since this could cause bootstrapping to fail.
This particular property rules out, for example, allowing the
symbol's function cell to become like a dynamically bound function
variable.
SOME POSSIBLE SOLUTIONS
The following are some possible solutions:
1) The symbol function cell could be eliminated as a global object and
the name to funcallable object mapping could be maintained within the
environment, as is the case in Scheme.
2) The generic function slot accessor functions could take an
environment argument and return information accordingly. This
was the solution I believe Patrick proposed.
3) We could simply leave it up to implementors to supply these
hooks, if they so choose.
Nice properties of each solution are:
1) The existence proof of Scheme and T shows that this solution can be
implemented. It also has a certain elegence.
2) No radical changes in existing Common Lisp implementations would be
needed.
3) No radical changes in the current spec for CLOS would be needed.
Nasty properties of each solution are:
1) Radical changes in existing Common Lisp compilers would be needed.
The issue of a single function/value cell is controversial, this could
be even more so.
2) This would complicate the metaclass protocol for generic functions
considerably. In particular, generic function slot accessors would need
to maintain data structures for mapping environments to methods, and
the dispatch function would need to do the "right" parameter specializer
to method function mapping, namely the one established when the method
was interpreted or loaded.
3) Implementation of object-oriented languages on the metaclass kernel
which resolve method inheritance at run time would have no support.
Optimizations of method lookup would be largely implementation dependent.
I don't like 2 is because it adds additional complexity to
the generic function protocol which I would rather avoid. I actually
like 1 best, but doubt we could ever get it implemented.
In the interests of wrapping up the loose ends of CLOS as expediently as
possible, I'd like to weigh in in favor of 3. While I think that the
metaclass kernel is an important part of CLOS, most people who want to
use it are more interested in the language for application implementation.
As I hope my previous posting has shown, the CLOS language (or programmer
interface) has no need for maintaining a seperate definition of generic
functions and methods in the compile time environment, since there is
no information about methods and generic functions previously compiled in a
file which needs to be portably transferred from form to form. In addition,
although the lack of this capability made implementation difficult,
the implementation of CommonObjects on the PCL kernel has shown that
a language which resolves most of method inheritance at compile time
can be done.
∂27-Aug-87 1656 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Solutions to Name/Object Mapping for Generic Functions
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 27 Aug 87 16:55:33 PDT
Received: from relay2.cs.net by RELAY.CS.NET id aa09283; 27 Aug 87 19:42 EDT
Received: from ti-csl by RELAY.CS.NET id aa05932; 27 Aug 87 19:31 EDT
Received: from dsg by tilde id AA00730; Thu, 27 Aug 87 16:33:04 CDT
Received: From Jenner By dsg Via CHAOS-NET With CHAOS-MAIL; Thu, 27 Aug 87 15:06:36 CDT
Message-Id: <2766081947-606167@Jenner>
Date: Thu, 27 Aug 87 15:05:47 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: kempf%hplabsz@hplabs.hp.com
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Solutions to Name/Object Mapping for Generic Functions
In-Reply-To: Msg of Thu, 27 Aug 87 10:51:21 MST from kempf%hplabsz@hplabs.hp.com
THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
The following are some possible solutions:
1) The symbol function cell could be eliminated as a global object and
the name to funcallable object mapping could be maintained within the
environment, as is the case in Scheme.
2) The generic function slot accessor functions could take an
environment argument and return information accordingly. This
was the solution I believe Patrick proposed.
3) We could simply leave it up to implementors to supply these
hooks, if they so choose.
If you are talking about name-to-generic-function mapping, 2 is not what
I have proposed. Name-to-generic-function mapping shouldn't depend on
the metaclass protocol since it should behave the same as
name-to-regular-function. Not being affected by the metaclass protocol,
it can be left to the implementation. The hook should be specified
though. If some implementations decide to ignore the environment,
that's fine. Since the environment is going to be passed explicitly(see
Moon's reponse to my proposal), we either need a new primitive for that,
or change SYMBOL-FUNCTION to accept an environment argument. A new
primitive for metaclass programmers is probably the best thing to do.
However I object to 3 since it will make serious metaclass programming
non portable.
Patrick.
∂27-Aug-87 1908 kempf%hplabsz@hplabs.HP.COM Re: Names to Objects and Compiler-environment
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 27 Aug 87 19:06:56 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Wed, 26 Aug 87 10:31:57 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Wed, 26 Aug 87 10:30:39 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Wed, 26 Aug 87 11:28:25 pdt
Message-Id: <8708261728.AA27357@hplabsz.hpl.hp.com>
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Names to Objects and Compiler-environment
In-Reply-To: Your message of Wed, 19 Aug 87 15:21:01 -0500.
<2765391661-13139657@Jenner>
Date: Wed, 26 Aug 87 11:28:22 MST
From: kempf%hplabsz@hplabs.HP.COM
THE PROBLEM
The fundamental problem I think we are trying to address with this
proposal is the transfer of information about class definitions
and potentially method definitions from form to form during a
file compilation. Such a transfer will necessary be implementation dependent,
but we would like to design an interface to the metaclass protocol which
is portable. The information on these definitions should
either not be a "real" definition or it should be a seperate and shadowing
definition from the definition in compiler's run time environment (if any).
The alternatives are to either replace the definition in the compiler's
run time environment, or to not propagate any information on class
and method definitions being compiled between forms. If we chose the
former solution (replacing the definition in the compiler's run
time environment) we face a bootstrapping problem, since a method
or class necessary for the compilation of a file may get redefined
while the file is being compiled, breaking the compiler (admittedly, this
may not occur very often, but, if it does, it could be very disabling).
The latter solution (not propagating any information) would place
an unreasonable burden on programmers using CLOS, since they would be
required to place class definitions and definitions of methods working
on those classes into seperate files. Usual practice in object-oriented
programming is to group class definitions and method definitions into
the same file, for easy reference.
THE PROPOSED SOLUTION
A solution has been proposed in which certain metaclass protocol
functions (generic and otherwise) take parameters which are "environments".
The exact nature of these environment parameters is unspecified, but
in order for them to be accessable to the top level macros DEFCLASS
and DEFMETHOD without adding alot of additional machinery to Common Lisp,
the most logical choice, as Moon has pointed out, is the macro &ENVIRONMENT
parameter.
The metaclass functions which Patrick has identified as being involved
in name to object mapping are:
CLASS-NAMED (aka SYMBOL-CLASS) - maps a symbol to a class
object having that name.
SYMBOL-FUNCTION - maps a symbol naming a (potentially generic)
function to the (potentially generic) function object.
GET-METHOD - ? according to pg. 2-39 of 87-002, this
takes a generic function object, list of method qualifiers,
and a list of parameter specializers (which, presumably,
are also objects) and produces the method.
Sonya has added:
GET-SETF-GENERIC-FUNCTION - maps a name for a generic
function into the generic function for doing the SETF.
I would argue that, of these, CLASS-NAMED and SYMBOL-FUNCTION are
at the right primitive level to discuss. My reasoning is as follows.
As the spec for GET-METHOD indicates, it is not doing a name to
object mapping but rather an object to object mapping. Thus
the more primitive operations CLASS-NAMED and SYMBOL-FUNCTION can
be used to find the objects, CLASS-NAMED to find the specializer
list, and SYMBOL-FUNCTION to find the generic function. As far
as GET-SETF-GENERIC-FUNCTION goes, it is doing a name to object
mapping, but the mapping is slightly bogus, since the name for a
SETF generic function is created, and the operation could just
as well be done by passing the generic function object for which the
SETF generic function was desired. The generic function object
might have to keep around information about it's SETF, however.
Alternatively, the algorithm for generating the SETF name could
be published (a user can find it simply enough anyway by
macroexpanding a SETF form) and we are back in the case where
SYMBOL-FUNCTION is the correct primitive for finding the
generic function.
Naturally, along with the functions for doing the name to object
mapping, the functions for doing a SETF will require an environment
argument as well. These would be the SETF functions for CLASS-NAMED
and for SYMBOL-FUNCTION.
Additional CLOS functions which Patrick has identified as possibly
requiring an environment argument are: ADD-METHOD, REMOVE-METHOD,
FIND-APPLICABLE-METHODS (presumably for use with CALL-NEXT-METHOD),
and ENSURE-GENERIC-FUNCTION. While these do not explicitly
do name to object mapping, I believe the logic here is the following:
ADD-METHOD, REMOVE-METHOD - addition and removal of a method from
a generic function is dependent on the environment, since a
different method definition may be desired on a generic function
in the compile time environment from what is available in the
compiler's run time environment (the "outside" or "top" environment).
FIND-APPLICABLE-METHODS - the compilation of a CALL-NEXT-METHOD
form will require access to methods as they are "defined" or,
at the very least, to the definitions compiled during a file
compilation, so the "current" definition is used for arranging
the method call, rather than the definition in the compiler's
run time environment.
ENSURE-GENERIC-FUNCTION-This does an implicit name to generic
function mapping, setting up any existing function (generic
also?) as a default method. Since it will probably use
SYMBOL-FUNCTION to retreive the function object bound to
the symbol's function cell, an environment parameter might
be needed to indicate which particular generic function
is required.
Of these, only ENSURE-GENERIC-FUNCTION takes a function name as an
an argument, the others all take generic function and other objects.
Hence, sensitivity to the processing environment need only be included
in ENSURE-GENERIC-FUNCTION, since only it will have to internally
resolve a name to object mapping.
One group of functions Patrick missed in his list is the metaclass
functions on pg. 3-25 of the metaobjec protocol specification.
They are all defined to take a name for the appropriate metaclass.
With the exception of DEFINE-METACLASS (which can be a macro anyway,
and thus use its &ENVIRONMENT parameter), the others could as well
be defined to operate on a class object which was a metaclass,
rather than directly on a metaclass name.
WHY CLASS DEFINITIONS NEED TO BE ENVIRONMENT SENSITIVE
I believe that an excellent case can be made for an environment argument
to CLASS-NAMED, and, correspondingly, that class definitions need to
be made both in the compile time environment (but *not* in the
compiler's run time environment) and at load time, as usual.
The arguments presented in the first section indicated why some way
of maintaining information on classes being defined needs to be propagated
between forms during a file compilation, independently of any definitions
in the compiler's run time environment.
An alternative for doing the definition "for real" is to maintain
information about definitions being compiled, then have the relevent
metaclass protocol functions distinguish whether the information about
a particular definition comes from the "for real" definition or from the
partial definition. I do not like this solution because it introduces
an additional element of complexity into the metaclass protocol which
somehow seems unnecessary, and sets up a more sharp distinction between
compiling a definition and evaluating it than simply switching
environments. CommonObjects did things this way, and it slowed down
compilation and made for some nasty case analysis. For example, handling
the distinction between the following two cases would be nontrivial
(in each case, the class FOO is also defined in the compiler's run time
environment):
Case 1:
(defclass foo () () )
(setf *global-var* (make-instance 'foo))
Case 2:
(defclass foo () () )
(eval-when (compile)
(setf *global-var* (make-instance 'foo)))
Though it could be disputed, I think the intent of Case 1 is to have
MAKE-INSTANCE use the FOO defined immediately above it, and that
the compiler, running in *not-compile-time-mode* (CLtL 69), should
defer instance creation and execution of the SETF until load time,
while, in the second case, instance creation and SETF should get done
at compile time using the definition in the compiler's run time
environment (*compile-time-too* mode) rather than the immediately
preceeding defintion, (except for KCL, which runs in *compile-time-too*
mode at the top level, but it is definitely in the minority).
If a compile time environment is used, then the EVAL-WHEN (COMPILE)
can simply be viewed as "popping" back to the compiler's run time
environment within the dynamic scope of the form, and returning to
the compile-time environment when the form ends.
The required behavior from DEFCLASS would be that the establishment
of a name to class object mapping is made via the &ENVIRONMENT
parameter, at compile time, and in the top level environment, at
load time. This suggests some way of obtaining the top level
environment for inserting the class name to object mapping.
Following Patrick's suggestion, a function GET-CURRENT-ENVIRONMENT
could be used. Another possibility is a special variable, *ENVIRONMENT*,
which would be bound to the current environment, similarly to how *PACKAGE*
is bound to the current package. I'd be interested in hearing if
this would have problems, as Moon's comments about GET-CURRENT-ENVIRONMENT
seem to indicate:
>If GET-CURRENT-ENVIRONMENT takes no arguments, then what you have is
>some form of dynamic scoping, rather than lexical scoping, and you can
>get scoping problems. Symbolics' implementation, and I believe TI's as
>well, currently works this way, using the special variable
>SYS:UNDO-DECLARATIONS-FLAG to inform macro expanders on behalf of which
>environment they are working. The genesis of this is historical and
>predates lexical scoping. This causes a number of subtle problems.
>CLOS should not make this mistake.
though I'm not quite sure what sorts of arguments GET-CURRENT-ENVIRONMENT
should have or how this relates to dynamic scoping. The idea with
*ENVIRONMENT* is that it would be bound to the current macroexpansion
environment, which may or may not be EQL to the &ENVIRONMENT parameter
of a macro (*MACROEXPAND-HOOK* could be used to modify whether this is
true or not) but they would, in any event, be the same "kind" of environment.
Exactly how the name to object binding is inserted into the environment
would, of course, be implementation dependent (but this could be
hidden within CLASS-NAMED).
In addition, DEFCLASS would naturally have to use definitions within
the &ENVIRONMENT parameter for things like determining inheritance
information necessary at compile time. What kinds of information
would be necessary? For the moment, let's ignore optimization information,
since things get a bit more complicated when it is taken into account.
Given this, we can rule out slot layout and number information, since
WITH-SLOTS :USE-ACCESSORS NIL (the only place it would potentially be needed)
should go through SLOT-VALUE. Possibly the slot :INITFORM (and any
additional initialization information) would need to be compiled, but
they would not have to be accessed by anyone else. The only really
important piece of information needed would be the SETF generic
function names for inherited slots, since these would be required for
expanding SETF forms at compile time. Most other aspects of inheritance
(modulo optimizations) could be handled at load time or run time.
In order to make things more convenient for the user, we may want
to define an interface function called CLASS-NAMED, which takes the
class out of the current environment, and a metaclass function,
called SYMBOL-CLASS, which requires an environment argument.
Corresponding SETFs would also be required. But this seems as
if it should be the only modification needed for dealing with
the name to class mapping.
As a side note, I did an experimental implementation of something
similar using the CommonObjects on CommonLoops implementation this spring.
The part modifying CLASS-NAMED to be sensitive to the compilation
environment worked very well, which leads me to believe that implementation
should be possible.
WHY SYMBOL-FUNCTION DOESN'T NEED AN ENVIRONMENT PARAMETER
FOR THE DEFAULT CLOS LANGUAGE
The other part of the initial proposal involved shadowing generic
functions and methods in the compile time environment by making
the name to function mapping dependent on the environment.
The effect would be to require SYMBOL-FUNCTION to have an environment
parameter, since SYMBOL-FUNCTION and its SETF are the means whereby a
name to (possibly generic) function mapping is established.
Note that any attempt to make the name to function mapping dependent
on the environment will inevitably have some serious reprecussions
for Common Lisp. In particular, the design of Common Lisp assumes
functions are named by symbols in a global name space, partitioned
through packages. These symbols have a globally accessable function
cell, which SYMBOL-FUNCTION, FBOUNDP, MAKFUNBOUND, and other accessor
function access. Thus function names are kind of like special variables
except they can't be dynamically bound, or, more precisely, like global
variables in other languages (Pascal, for example), where dynamic
binding is not available. The name to function mappings established
by FLET and LABELS are not available via. SYMBOL-FUNCTION.
Referring back to the initial motivation for including environment
sensitivity, namely information propagated from form to form, there
is only one case where one method might need to know something about
another 's definition during compilation: CALL-NEXT-METHOD. However,
ignoring optimizations for the moment, the characterization of
CALL-NEXT-METHOD as lexical in scope and dynamic in extend suggests
lookup of the next method could be done, at the latest, at run time
exactly as method dispatch is done. Knowledge about the classes
of the caller's parameters at compile time could be used to limit
the run time method search. Various further optimizations are possible,
but the most obvious require only the ability to do method lookup
and linking at load time.
WHY SYMBOL-FUNCTION MAY REQUIRE ENVIRONMENT DEPENDENCY IN THE
METACLASS PROTOCOL
Unfortunately, some object oriented languages resolve method inheritance
fully at compile time. CommonObjects is an example. CommonObjects
has a form similar to CALL-NEXT-METHOD (called CALL-METHOD) which
allows the programmer to specify a particular method on the direct
super (or on itself), and a function call to the method (via. a
special method symbol) is compiled in at compile time. Thus the
CALL-METHOD macro must have access to the symbol at compile time,
and the fasl loader must maintain a compile time to load time
mapping of the symbol. This is all implementation dependent, of
course, and this particular feature has given us much trouble
in developing the Portable CommonObjects implementation. The
point is, however, that compiling a file of CommonObjects methods
requires information on the methods previously compiled to be
propagated between forms.
As mentioned in the previous section, addition of an environment
parameter to SYMBOL-FUNCTION (and its SETF) would involve a
major change to the semantics of function symbols in Common Lisp.
Since the function cell is a globally accessable place, would
redefining a function in a particular environment still cause
the global definition to change? If so, then bootstrapping problems
could easily occur, since a definition which has just been compiled
should not be used in the compilation process. If not, then the
nature of the function cell as a globally accessable place is
compromised, since function invocations in the compiler's run
time environment will get one definition, while another definition
will be operative in the compilation environment.
∂28-Aug-87 0150 skeene@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Aug 87 01:50:47 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 217984; Fri 21-Aug-87 10:17:46 EDT
Date: Fri, 21 Aug 87 10:17 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Agenda for September meeting
To: kempf%hplabsz@hplabs.HP.COM
cc: Moon@STONY-BROOK.SCRC.Symbolics.COM, common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <8708202023.AA19448@hplabsz.hpl.hp.com>
Message-ID: <870821101706.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 14:23:16 MST
From: kempf%hplabsz@hplabs.HP.COM
With regard to the spec documentation, I'd like to put in a vote for an ASCII
version to go on parcvax, along with the portable source, so people don't
have to be working in the dark with it. The ASCII version doesn't
necessarily have to be up to the current level of discussion and
decision within the committee (indeed, it probably shouldn't) but should
reflect approximately what is implemented.
Please don't confuse the spec documentation with documentation for an
implementation. These are two very different things!
∂28-Aug-87 1912 Moon@STONY-BROOK.SCRC.Symbolics.COM Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 28 Aug 87 19:12:23 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 223738; Fri 28-Aug-87 22:13:25 EDT
Date: Fri, 28 Aug 87 22:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870828221318.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Draft of a new object creation proposal based on CLOS subcommittee
discussions July 2, 1987.
-foo- means the word foo in italics. FOO means the word foo in boldface.
ONE NEW IDEA YOU HAVEN'T SEEN BEFORE
There is a new lambda-list-keyword, &METHOD-KEY, which is only valid in
DEFGENERIC-OPTIONS and DEFGENERIC-OPTIONS-SETF. The syntax of the lambda-list
in these macros becomes
({-var-}+
[&optional {-var-}*]
[&rest -var-]
{ [&key {-var- | ((-keyword- -var-))}* [&allow-other-keys]]
| [&method-key [&allow-other-keys]] })
The meaning of &METHOD-KEY is that the specific set of named arguments
accepted by the generic function varies depending on the positional arguments.
The named arguments accepted by the generic function for a particular call are
the union of the named arguments accepted by the applicable methods. There is
no attempt to exclude methods that are applicable but are not actually called.
Note that in standard method combination, all applicable methods are
potentially callable, if CALL-NEXT-METHOD is used. A method that has &REST,
but not &KEY, does not affect the set of acceptable named arguments. If the
lambda-list of any applicable method or of the DEFGENERIC-OPTIONS has
&ALLOW-OTHER-KEYS, all named arguments are accepted by the generic function.
The implementation of &METHOD-KEY is in two parts: The macro expansion of
DEFMETHOD, when the generic function uses &METHOD-KEY, is altered to save a
list of the acceptable named-argument names in a slot of the method object and
to put &ALLOW-OTHER-KEYS into the lambda-list of the function. If the
lambda-list already contains &ALLOW-OTHER-KEYS, then that symbol is stored in
place of the list of acceptable named-argument names (which would be
infinite). The function METHOD-NAMED-ARGUMENTS retrieves this list or symbol.
Secondly, the generic-function-to-method dispatching mechanism must check the
validity of the argument list when the generic function uses &METHOD-KEY and
does not use &ALLOW-OTHER-KEYS. This is accomplished by collecting the
acceptable named-argument names from the applicable methods and checking the
arguments against the union of those lists. If for any applicable method
METHOD-NAMED-ARGUMENTS returns &ALLOW-OTHER-KEYS, the whole check is skipped.
CONCEPTS TO BE ADDED TO 87-002
-named argument-. We use the term "named argument" instead of "keyword
argument" (as in CLtL) for &key arguments, because CL-Cleanup issue
KEYWORD-ARGUMENT-NAME-PACKAGE has stated that the names of &key arguments
do not have to be keyword symbols.
-named argument name-. The symbol that identifies a named argument in
an argument list. This is typically a keyword, but is not required to be.
The named-argument name should not be confused with the variable name
of the parameter variable. These two symbols typically have the same
name and are typically in different packages, but that is not required.
-initarg-. An initarg (initialization argument) is a named argument that
can be used to control object creation and initialization. The &key
arguments to MAKE-INSTANCE are initargs. Each initarg has a name, which is
a symbol, and may have a value, which is any Lisp object. It is often
convenient to use keyword symbols to name initargs, but the name of an
initarg can be any symbol, including NIL.
-initarg list-. An initarg list (initialization argument list) is a list
of alternating initarg names and values. Its structure is identical to a
property list and also identical to an &key argument list. As in those
lists, if an initarg name appears more than once in an initarg list, the
leftmost occurrence supplies the value and the remaining occurrences are
ignored. The arguments to MAKE-INSTANCE, after the first, are an initarg
list. As in an &key argument list, :ALLOW-OTHER-KEYS can appear in an
initarg list, and if its value is non-NIL, error-checking of initarg names
is disabled.
-slot-filling initarg-. An initarg associated with a slot. If the initarg
has a value, the value is stored into the slot of the newly-created object,
overriding any initform associated with the slot. -(What about shared
slots?)- A single initarg can fill more than one slot.
-method-implemented initarg-. An initarg associated with a method. When
an object is created, the method is called with the initarg's value as an
argument and the method uses the value in any way it likes. If the initarg
has no value, the method's lambda-list supplies a default value. A single
initarg can be implemented by more than one method. An initarg can be both
slot-filling and method-implemented.
CHANGES TO 87-002 FEATURES
DEFCLASS gets a new :INITARG slot option, which is followed by a symbol.
The symbol becomes the name of a slot-filling initarg for this class.
DEFCLASS gets a new :DEFAULT-INITARGS option, which is followed by an initarg
list. Each value in this list is a form that is evaluated by MAKE-INSTANCE if
the initarg does not already have a value. The forms are evaluated in the
lexical environment in which the DEFCLASS form was evaluated.
Method-implemented initargs are defined simply by defining a method for
INITIALIZE-INSTANCE or ALLOCATE-INSTANCE; each named-argument name in the
method's lambda-list becomes a method-implemented initarg for all classes for
which this method is applicable.
Initarg inheritance: The effective set of slot-filling initargs for a class C
is the union of the slot-filling initargs defined by C and its superclasses.
The effective set of method-implemented initargs for a class C is determined
by method inheritance.
Default-initargs inheritance: [same as for the :INITFORM slot option]
Changes to Lambda-list Congruence Rules (p.1-20): Rules 1, 2, and 6 remain
the same, except for wording problems, while rules 3-5 need to be replaced
to implement &METHOD-KEY and to fix the interaction among &KEY, &REST, and
&ALLOW-OTHER-KEYS. The new rules for congruence are the following:
These rules define the congruence of a set of lambda-lists, including the
lambda-list of each method for a given generic function and the lambda-list
specified with DEFGENERIC-OPTIONS, if present. For -SETF methods, these
rules apply to the effective lambda-list produced by combining the two
specified lambda-lists according to the rules on page nnn.
1. Each lambda-list must have the same number of required parameters.
2. Each lambda-list must have the same number of optional parameters.
Each method can supply a different default for an optional parameter.
3. If any lambda-list uses &REST, &KEY, or &METHOD-KEY, each lambda-list
must use one or more of these. Note that &METHOD-KEY is only valid in
DEFGENERIC-OPTIONS.
4. If the DEFGENERIC-OPTIONS does not use &METHOD-KEY, or there is no
DEFGENERIC-OPTIONS, each method that uses &KEY and does not use
&ALLOW-OTHER-KEYS must specify the same named-argument names.
5. The use of &ALLOW-OTHER-KEYS need not be consistent across lambda-lists.
6. The use of &AUX need not be consistent across methods.
Rules when initargs are duplicated:
The :INITARG slot-option may be specified more than once for a given slot.
A single initarg can initialize more than one slot if the same initarg name
appears in more than one :INITARG slot-option.
If two initargs that initialize the same slot, with the same or different
names, are given in the arguments to MAKE-INSTANCE, the leftmost of these
initargs in the initarg list prevails.
If two different initargs that initialize the same slot have default values,
the initarg that appears in a :INITARG slot-option in the most specific
class prevails, or if they appeared in the same class, the one leftmost in
the slot-options list prevails.
It is valid for a given initarg name to be defined more than once as a
slot-filling initarg, as a method-implemented initarg, or both.
NEW FUNCTIONS TO BE ADDED
In this section, I have only sketched each function, for the sake of brevity.
Full writeups can be constructed once the overall framework has been agreed
upon. Functions are in alphabetical order. By coincidence, all functions
listed are generic and expected to specialize on their first argument.
(ALLOCATE-INSTANCE class &method-key &allow-other-keys) => instance
Metausers can replace the system-supplied, implementation-dependent
method for this.
(CHECK-INITARGS class initarg-list)
Metausers could replace the system-supplied method that implements the
normal rules for initarg validity.
(CLASS-ALL-INITARGS class) => list of initarg names (includes inherited)
(CLASS-DIRECT-INITARGS class) => list of initarg names
(CLASS-ALL-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
(CLASS-DIRECT-INITARG-DEFAULTS class)
=> ((initarg-name default-value-function)...)
(CLASS-ALL-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(CLASS-DIRECT-SLOT-INITARGS class) => ((initarg-name slot-name...)...)
(COMPUTE-APPLICABLE-METHODS generic argument-list) => list of methods
(DEFAULT-INITARGS class initarg-list) => initarg-list
The system-supplied method implements the :DEFAULT-INITARGS class option.
[This could specialize on instance instead of class, but I don't
see any point to that.]
(ENCACHE-INITARG-INHERITANCE class)
This is called by the system at least once before a class is instantiated,
and is called again whenever anything relevant changes. System-supplied
methods for this conspire with methods for CHECK-INITARGS, etc., to make
MAKE-INSTANCE faster. Users with their own caching needs can add methods
for this generic function.
(ENCACHE-METHOD-INHERITANCE class)
(ENCACHE-SLOT-INHERITANCE class)
(INITIALIZE-INSTANCE instance &method-key &allow-other-keys)
Users define :AFTER methods for this to create method-implemented initargs.
The primary method for this is system-supplied and takes care of the
slot-filling initargs.
(MAKE-INSTANCE class &key -initargs-...) => instance
(METHOD-NAMED-ARGUMENTS method) => list of symbols or &ALLOW-OTHER-KEYS
(SLOT-BOUNDP instance slot-name) => boolean
Allows writing INITIALIZE-INSTANCE methods that only initialize slots if they
haven't been initialized already.
(SLOT-MAKUNBOUND instance slot-name) => NIL
PROCEDURAL DEFINITION OF MAKE-INSTANCE
MAKE-INSTANCE behaves as if it was defined as follows, except that certain
optimizations are permitted, as detailed below.
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
Optimization is possible, including inlining and constant-folding of method
lookup and method bodies, provided that the programming environment either
prohibits redefining these methods or updates everything when they are
redefined. A possible example implementation would be that MAKE-INSTANCE has
a separate method for every class, which is automatically written and compiled
by the system.
This optimization relies on the ENCACHE-INITARG-INHERITANCE generic function
and some unpublished slots of STANDARD-CLASS.
Because of optimization, methods for the generic functions listed may not
actually be called on every call to MAKE-INSTANCE, or may not receive
exactly the arguments that would be expected. For example, CHECK-INITARGS
may actually be called before DEFAULT-INITARGS rather than after, if it has
already been determined that the default initargs will pass CHECK-INITARGS.
Additional explicit details of permissible optimization will need to be set
forth.
MEETING OF STATED DESIGN GOALS
Lexical proximity of concepts--the declaration of an initarg as valid,
the specification of what it does, and the default if it is not supplied
are all together, in a slot specifier or in a method lambda-list.
Simple ways to do simple things--slot-filling initargs don't require the
user to write any code. Method-implemented initargs work just like
ordinary function arguments as far as the user is concerned.
Minimal number of new languages--the only addition to Common Lisp is
&METHOD-KEY.
Ability to do everything at some level--the underlying procedural level
is available. Functions to access all the direct and inherited
information are documented.
Underlying mechanism is exposed so user can use it for other things,
rather than abusing instance creation as the only way to access the
mechanism--the combination of &method-key, method-named-arguments,
compute-applicable-methods, and encache-initarg-inheritance provides
everything the user needs.
∂30-Aug-87 1946 RPG Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
On July 27 Kempf mailed a note about the description of the class
precedence list algorithm. Because I was away until yesterday, I
was not able to respond:
Kempf writes:
1) The use of the term "partial order" on pg. 1-15, paragraph 1
implies a relation on R which is reflexive, antisymmetric, and
transitive. From the text of the paragraph, this relation is
presumably the "is a subclass of" relation. However, earlier in
the document, reflexivity is explicitly excluded from the "is a
subclass of" relation (pg. 1-4, paragraph 3), since a class is
defined to be neither a superclass nor a subclass of itself.
Either the partial order needs to be replaced with a different
order not requiring reflexivity (semiorder, etc.) or the "is a
subclass of" relation needs to be redefined so that it is
reflexive. Note that the latter solution is used in more
technical treatments of typing systems (e.g. Cardelli and
Wegner, Computing Surveys, 17, 1985, pp. 471-522).
Knuth points out that one can define partial orderings using ``less than
or equal'' and so does not require the antisymmetric condition. We should
be more explicit here about it and define the partial ordering on a true
reflexive, antisymmetric, and transitive relation.
Kempf writes:
4) The formal description of class precedence list calculation
on pg. 1-15, paragraph 3 is lacking a condition. In the third
line, it is not sufficient just to require the existence of an
index i, but also its minimality. As a counterexample,
consider R := {(c1,c2) (c2,c3) (c3 c5) (c2 c4) (c4 c6)} The
inheritance graph for this is....
Well, this is the result of a misreading of the algorithm. However,
this is sufficient to require a rewrite of the description. As an aside
to JAK, let me point out the following: his example was:
c5 c6
| |
c3 c4
| |
\ /
\ /
c2
|
c1
The relations used to define the partial ordering are:
{(c1 c2)(c2 c3)(c2 c4)(c3 c4)(c3 c5)(c4 c6)}
The key one is that c3 precedes c4.
When the CPL is [c1 c2], there is only one class with no predecessors -
C3.
I believe the description of the algorithm to be correct, but I stand accused of
and confess to it being a difficult description. I will volunteer to try to fix
it up.
By the way, have we thought about various means of making the CPL more
accessible, such as what New Flavors does?
∂30-Aug-87 2009 RPG Miscellaneous decisions taken or to be taken
To: common-lisp-object-system@SAIL.STANFORD.EDU
Moon writes:
The document says it has dynamic extent; we need to be sure that we
really mean that. In July we said "implementation flexibility, not
really a language thing", but I'm damned if I can figure out what
that means (optimizing calculation of the effective method?).
The document says ``the binding for the local variable CALL-NEXT-METHOD
has lexical scope and dynamic extent.''
The idea is that a user would not even be allowed to create a closure
that refered to CALL-NEXT-METHOD. I suppose he could, but he'd get some
global defintion for CALL-NEXT-METHOD. We intend to not provide a poor man's
continuation mechanism. I didn't think we even had anything as sophisticated
as hierarchy redefinition in mind when we wrote this. The description needs to
be clearer.
-rpg-
∂30-Aug-87 2017 RPG Agenda
To: common-lisp-object-system@SAIL.STANFORD.EDU
The agenda seems fine to me. The key to making the meeting work is for
people to dedicate time to studying the proposals and doing what they
have volunteered to do. I, for example, will get to work on the
anonymous generic function progosal tomorrow, and you will all have it
within a week.
Because I just returned from Europe, I don't even know what arrangements
Linda has made. But, again, there is no territorialness in what they are,
it is a matter of someone volunteering to do the work and then doing it.
Danny was also in Europe, and no one else had stepped forward.
On the document: I earlier promised to produce a minimal TEX macro file
so that people could roll their own. It was a lack of time on my part that
prevented that rather than some sinister plot. I hope I can get that done in
a day and put it out on SAIL along with the TEX sources. The problem with the
current macro file is that it is many dozens of pages long and contains the
book layout definition for all of Lucid's manuals.
-rpg-
∂30-Aug-87 2024 RPG Name That Class!
To: Common-lisp-object-system@SAIL.STANFORD.EDU
Before I left on my ill-fated trip to Europe (where I confronted face-to-face,
once more, my muse) I wrote out some examples of how class objects and their
names interacted. The idea was to explore what it meant to build a hierarchy
with names (using DEFLCASS) and with class objects (blasting fields). I think
these examples are right (I could be wrong) and they might strike some as
odd, they are generally in accord with acceptable behavior of functions and
the symbols that name them (and DEFSTRUCT names and types as well). I send them
in hopes they might help stimulate thought on the issues:
1. (defclass foo ...)
(let ((a (class-named 'foo)))
(defclass foo ...)
(eq a (class-named 'foo))) => T
This has been agreed to be the best sufficient way to achieve the
old-methods-still-work behavior.
2. (defclass foo ...)
(let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c)
(eq (class-named 'foo) c)) => ?
MAKE-INSTANCE is not psychic, so it must cons. It seems that (DEFLCASS FOO ...)
is equivalent to
(let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c)
c)
Note that there is no similar expression in CLtL to which DEFTSRUCT is
equivalent. Therefore the EQ must return NIL. This implies that (setf
(class-named ...) ...) is smart and worries about the EQness between the
previous class, if it exists, and the new one.
3. (let ((c (make-instance 'standard-class)))
(setf (<various aspects> c) <certain values>)
(setf (class-named 'foo) c) ;foo otherwise undefined
(eq (class-named 'foo) c)) => ?
Why should (setf (class-named ...) ...) unnecessarily cons? Therefore
the EQ should return T.
4. (defclass foo ...)
(defclass baz ...)
(let ((c1 (class-named 'foo))
(c2 (class-named 'baz)))
(setf (class-named 'baz) (class-named 'foo))
;;; (eq c1 c2) => NIL
(eq (class-named 'foo) (class-named 'baz))) => ?
Because (eq c1 (class-named 'foo)) => T, (eq c1 c2) => NIL, and (eq c2
(class-named 'baz)) => T, this must return NIL.
5. (defclass foo ...)
(defmethod f ((x foo)) ...) ;no other methods
(defclass baz ...)
(defmethod g ((x baz)) ...) ;no other methods
(setq instance1 (make-instance 'foo))
(setq instance2 (make-instance 'baz))
(rotatef (class-named 'foo) (class-named 'baz))
(f instance1) => well-defined?
(f instance2) => well-defined?
(g instance1) => well-defined?
(g instance2) => well-defined?
The first generic function invocation is well-defined; the second is an
error of some sort; the third is an error of some sort; the fourth is
well-defined.
6. (defclass c1 (c2 c3) ...)
(defclass c2 ...)
(defclass c3 ...)
(defmethod f ((x c2)) ...) ;no other methods
(setq instance1 (make-instance 'c1))
;;; Flush the superclass link from C1 to C2
(setf (class-super-classes (class-named 'c1)) `(,(class-named 'c3)))
(f instance1) => well-defined?
I don't know what this should do, but I suspect the expression (f instance1)
is not well-defined because the SETF alters the topology of the graph.
It seems that once a name is given to a class, the symbol that is the
name and the storage for that class are linked forever unless something
like
(setf (class-named 'foo) nil)
is defined to work.
It is also clear that the the applicability of methods within a class
graph depends on the topology of the graph and not on the substance of the
classes in that graph. If a user were to mistakenly exchange the names of
two classes in a graph at the outset, he would not be able to correct that
naming error using CLASS-NAMED and (SETF (CLASS-NAMED ...) ...) - example
4 shows this. He would have to alter the superclass slots in the classes
surrounding the ones he wishes to switch, according to the technique in
example 6, assuming that would even work.
Enjoy!
-rpg-
∂30-Aug-87 2054 Moon@STONY-BROOK.SCRC.Symbolics.COM Class Precedence List
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 30 Aug 87 20:53:31 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 224284; Sun 30-Aug-87 23:54:35 EDT
Date: Sun, 30 Aug 87 23:54 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Class Precedence List
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: The message of 30 Aug 87 22:46 EDT from Dick Gabriel <RPG@SAIL.STANFORD.EDU>
Message-ID: <870830235432.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 30 Aug 87 1946 PDT
From: Dick Gabriel <RPG@SAIL.STANFORD.EDU>
By the way, have we thought about various means of making the CPL more
accessible, such as what New Flavors does?
Yes, I signed up to write a proposal that would try to satisfy Gregor's
objections to the proposal I presented previously, as best as I could
understand them. I haven't done it yet, though. I've been putting my
time into make-instance instead.
∂31-Aug-87 0802 kempf%hplabsz@hplabs.HP.COM Re: Agenda for September meeting
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 31 Aug 87 08:02:20 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Mon, 31 Aug 87 08:00:47 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 31 Aug 87 08:00:25 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 31 Aug 87 09:01:03 pdt
Message-Id: <8708311501.AA16453@hplabsz.hpl.hp.com>
To: "Sonya E. Keene" <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Agenda for September meeting
In-Reply-To: Your message of Fri, 21 Aug 87 10:17:00 -0400.
<870821101706.9.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Mon, 31 Aug 87 09:01:00 MST
From: kempf%hplabsz@hplabs.HP.COM
> Date: Thu, 20 Aug 87 14:23:16 MST
> From: kempf%hplabsz@hplabs.HP.COM
> With regard to the spec documentation> , I'd like to put in a vote for an ASCII
> version to go on parcvax, along with the portable source, so people don't
> have to be working in the dark with it. The ASCII version doesn't
> necessarily have to be up to the current level of discussion and
> decision within the committee (indeed, it probably shouldn't) but should
> reflect approximately what is implemented.
> Please don't confuse the spec documentation with documentation for an
> implementation. These are two very different things!
I hope I'm not. My concern is that, if the process of finalizing the spec
and the portable implementation continue in tandem, as seems to be happening,
people will want to have a more accessable copy of the spec. Of course,
there will be differences between the spec and the implementation, and
these should probably be documented. Additionally, should a decision be made
not to pursue the portable implementation (which would be tragic, in my
opinion) then there would be little need. There are lots of people using the
current PCL/half CLOS at universities and such, and I think they'd like to
have a copy.
But I most whole-heartedly agree that the spec and any particular
implementation of it are seperate.
∂31-Aug-87 1914 MLY@AI.AI.MIT.EDU RPG's recent typo.
Received: from AI.AI.MIT.EDU by SAIL.STANFORD.EDU with TCP; 31 Aug 87 19:14:25 PDT
Date: Mon, 31 Aug 87 22:18:06 EDT
From: Richard Mlynarik <MLY@AI.AI.MIT.EDU>
Subject: RPG's recent typo.
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <248781.870831.MLY@AI.AI.MIT.EDU>
Perhaps DEFCLASS could be renamed DEFTSTRUCT.
∂01-Sep-87 1150 Gregor.pa@Xerox.COM Re: Name That Class!
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Sep 87 11:49:53 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 SEP 87 10:11:53 PDT
Date: 1 Sep 87 10:11 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Name That Class!
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 30 Aug 87
20:24 PDT
To: RPG@SAIL.STANFORD.EDU
cc: Common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870901-101153-7058@Xerox>
Your first example is right. But there is a mistaken assumption in your
second example that throws all the others off. Specifically, you say
that:
It seems that (DEFLCASS FOO ...)
is equivalent to
(let ((c (make-instance 'standard-class))) (setf
(<various aspects> c) <certain values>) (setf (class-named
'foo) c) c)
But this isn't right. (defclass foo ...) is equivalent to:
(let* ((existing (class-named 'foo t))
(new (if existing
(class-for-redefinition existing)
(make-instance 'standard-class))))
(setf (class-named 'foo) new)
(update-class new ..)
new)
Given this clarification, its clear that (for instances of
standard-class) the rest of your examples should return:
2. T
3. T
4. T
The point is that class-named has no smarts (remember that as much as
possible we don't want to do things that just couldn't map into a
Lisp-1, and certainly set! has no smarts). class-for-redefinition is
where all the smarts is.
∂01-Sep-87 1258 RPG Name That Class!
To: common-lisp-object-system@SAIL.STANFORD.EDU
It would be nice if it turned out that the relationship between
a class and its name could be as clean as the relationship between
a symbol and its value, but this is not the case: We can already
ask of a class its name.
When I wrote these examples I thought of two parallel activities going
on in two CLOS's right next to each other - one in which a user was using
DEFCLASS to build up a hierarchy and one in which a user was using
anonymous classes to build up the same hierarchy. My assumption about the
equivalence of DEFCLASS and the LET-expression was derived from a belief
that simplicity of model was desirable.
I don't, now, believe that the behaviors I listed in my message are alarming
(though I did originally) because one can imagine a Common Lisp in which
(defun f (...)...)
and
(setf (symbol-function 'f) (function (lambda (...)...)))
are equivalent and similar behaviors hold to the ones in that message (that
is, SETF of SYMBOL-FUNCTION is smart).
We also run into the problem that Common Lisp already treats types as a
sort-of subclass of SYMBOL, and so the tight name-to-object mapping
described in my message is not altogether out of line with an attempt to
integrate classes with types.
We haven't really talked about what DEFCLASS is equivalent to yet,
so I suppose there are now two proposals as to what that might be on
the table.
-rpg-
∂01-Sep-87 1300 RPG Anonymous Generic Function Proposal (Draft 1)
To: common-lisp-object-system@SAIL.STANFORD.EDU
There are 3 cases to consider:
1. Purely anonymous generic functions, corresponding to
(function (lambda ...)) in Common Lisp.
2. A set of named generic functions to be used within a particular
body, corresponding to (labels ...) in Common Lisp. An analog
to FLET might be appropriate also.
3. A means of extending a generic function currently defined on a
symbol (name). This corresponds to nothing in Common Lisp.
Here is a proposal, inspired by Guy Steele, which covers case 1:
(generic (lambda ...)
(lambda ...)
(lambda ...)
...))
This special form produces a generic function with the lambda-expressions
as the methods. This is about as similar to the FUNCTION syntax as can
be rationally gotten.
To cover case 2 we define an analog to Common Lisp LABELS, but instead of
functions the user defines methods:
(generic-labels ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
At this point it is easy to extend FLET similarly:
(generic-flet ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
The simplest means of producing an anonymous recursive generic function is:
(generic-labels ((self (...)...(self...)...)
(self (...)...(self...)...)
...)
#'self)
Notice that the special form FUNCTION will need to be amended in CLtL to
be able to produce a generic function, but this should be a natural fallout
of making a generic function a subtype of FUNCTION.
Handling case 3 is more difficult, because there is no corresponding
Common Lisp form to do a similar thing for functions. A danger is to
inadvertently design a form that will also accomplish the dynamic binding
of a function associated with a symbol.
(with-added-methods ((print (...)...)
(print (...)...)
(read (...)...)
(read (...)...)
(read (...)...))
<body>)
Among the things that could have been included in this proposal is
the ability to have the method functions be able to call each other
without going through the generic function object. However, this obscure
case can be hacked together using add-method etc, and I don't believe
it deserves a special syntax. (It might be so obscure you cannot understand
this description, but that only reinforces my argument.)
-rpg-
∂01-Sep-87 1823 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 1)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 1 Sep 87 18:23:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 01 SEP 87 18:19:05 PDT
Date: 1 Sep 87 18:18 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 1)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
13:00 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870901-181905-7824@Xerox>
(with-added-methods ((print (...)...)
(print (...)...)
(read (...)...)
(read (...)...)
(read (...)...))
<body>)
Is this strictly lexical (only calls within the <body> have the added
methods), or is it dynamic (calls from any called function see the
methods, but the methods are removed when the fom is exited). Both are
useful I think.
danny
∂01-Sep-87 2317 RPG Anonymous Generic Function Proposal (Draft 2)
To: common-lisp-object-system@SAIL.STANFORD.EDU
Draft 1 is amended to take into account Danny's comment.
There are 3 cases to consider:
1. Purely anonymous generic functions, corresponding to
(function (lambda ...)) in Common Lisp.
2. A set of named generic functions to be used within a particular
body, corresponding to (labels ...) in Common Lisp. An analog
to FLET might be appropriate also.
3. A means of extending a generic function currently defined on a
symbol (name) or lexically. This corresponds to nothing in
Common Lisp.
Here is a proposal, inspired by Guy Steele, which covers case 1:
(generic (lambda ...)
(lambda ...)
(lambda ...)
...))
This special form produces a generic function with the lambda-expressions
as the methods. This is about as similar to the FUNCTION syntax as can
be rationally gotten.
To cover case 2 we define an analog to Common Lisp LABELS, but instead of
functions the user defines methods:
(generic-labels ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
This form produces 2 new generic functions, FOO and BAR.
At this point it is easy to extend FLET similarly:
(generic-flet ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
The simplest means of producing an anonymous recursive generic function is:
(generic-labels ((self (...)...(self...)...)
(self (...)...(self...)...)
...)
#'self)
Both GENERIC-LABELS and GENERIC-FLET produce new generic functions. The
fact that a generic function is already bound to a variable of the same
name or to a symbol is irrelevant to the operation of these forms.
Notice that the special form FUNCTION will need to be amended in CLtL to
be able to produce a generic function, but this should be a natural fallout
of making a generic function a subtype of FUNCTION.
Handling case 3 is more difficult, because there is no corresponding
Common Lisp form to do a similar thing for functions. A danger is to
inadvertently design a form that will also accomplish the dynamic binding
of a function associated with a symbol.
(with-added-methods <generic-function> (<methods>*) . <body>)
This takes a generic function and a list of methods specified as
lambda-expressions, extends the generic function by adding the appropriate
methods, and then executes the forms in <body> as if they were in a PROGN.
When WITH-ADDED-METHODS exits, the added methods are removed. Any flow of
control out of the WITH-ADDED-METHODS causes the methods to be removed.
Notice that this handles both anonymous and named generic functions.
For example:
(generic-flet ((foo (...)...) (foo (...)...))
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
(with-added-methods #'foo ((lambda (...)...)) <body>)))
-rpg-
∂02-Sep-87 1149 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Sep 87 11:49:10 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 02 SEP 87 11:49:27 PDT
Date: 2 Sep 87 11:49 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
23:17 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870902-114927-8581@Xerox>
When WITH-ADDED-METHODS exits, the added methods are removed.
Any flow of control out of the WITH-ADDED-METHODS causes the
methods to be removed.
I still find this ambiguous.
Consider
(defmethod fie (x) 0)
(defun foo (x)
(with-added-methods fie ((lambda ((x P1)) 17))
(cons (fie x) (fum x)))
(defun fum (y) (fie y))
(foo (make-instance 'P1))
==> (17 . 17)
or
==> (17 . 0)
∂02-Sep-87 1224 Pavel.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 2 Sep 87 12:24:04 PDT
Received: from Semillon.ms by ArpaGateway.ms ; 02 SEP 87 12:10:50 PDT
Date: Wed, 2 Sep 87 12:10:46 PDT
From: Pavel.pa@Xerox.COM
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: <870902-114927-8581@Xerox>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870902-121050-8628@Xerox>
Another question about the proposal: What is the intent with respect to
multi-process environments? During the time that WITH-ADDED-METHODS is
active, should the other processes see the added methhods or not? I
would hope not;; this should have the same sort of behaviour as special
variables.
Pavel
∂02-Sep-87 1534 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Another try on object creation
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 2 Sep 87 15:34:34 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ab03266; 2 Sep 87 17:59 EDT
Received: from ti-csl by RELAY.CS.NET id af13392; 2 Sep 87 17:48 EDT
Received: from Jenner by tilde id AA19802; Wed, 2 Sep 87 16:39:20 CDT
Message-Id: <2766605837-15560752@Jenner>
Date: Wed, 2 Sep 87 16:37:17 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Subject: Re: Another try on object creation
In-Reply-To: Msg of Fri, 28 Aug 87 22:13 EDT from "David A. Moon" <Moon@scrc-stony-brook.arpa>
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
(defmethod make-instance ((class-name symbol) &rest initargs)
(apply #'make-instance (symbol-class class-name) initargs))
I have a question: Why don't you use a class prototype to call
default-initargs and check-initargs?
Patrick.
∂02-Sep-87 2013 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 2 Sep 87 20:13:02 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 226977; Wed 2-Sep-87 23:13:58 EDT
Date: Wed, 2 Sep 87 23:13 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <2766605837-15560752@Jenner>
Message-ID: <870902231340.4.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Wed, 2 Sep 87 16:37:17 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
(defmethod make-instance ((class standard-class) &rest initargs)
(setq initargs (default-initargs class initargs))
(check-initargs class initargs)
(let ((instance (apply #'allocate-instance class initargs)))
(apply #'initialize-instance instance initargs)
instance))
I have a question: Why don't you use a class prototype to call
default-initargs and check-initargs?
That's the way the notes from the meeting had it, but in my proposal
I changed that for two reasons. One is that this was the only use
of prototypes, so by changing this we can eliminate the need to expose
that concept; it makes the standard simpler. The second reason is
a little more complex: in trying to figure out why there was such
apparent randomness, with some functions generic on the instance and
others generic on the class, I decided it must be that functions generic
on the instance can have methods defined by ordinary users, and can
have those methods combined with inheritance, while functions generic
on the class are part of the metaclass protocol and you only write
methods for them if you are doing over part of the implementation.
At the meeting we said that it was "hard to make default-initargs
and check-initargs generic" and left it at that. If you think about
check-initargs, all the checking has to be in one place; there is
no way to do it by combining inherited methods, each of which checks
one class's initargs. In fact there is one method for check-initargs
which looks at the slot-initargs and the lambda-lists of the applicable
methods and decides what to do. Therefore, I decided check-initargs
must be a metaclass method. The alternative would have been to have
a check-initarg generic function that checks one argument at a time,
which seemed unduly complex.
Less clear is defaulting, but what decided me there was that at the
meeting there was a move to combine default-initargs and check-initargs
into a single operation, in which case they would have to be generic on
the same thing. I don't really see much usefulness in users defining
their own default-initargs methods, when they are not working at the
metaclass level, so to keep things simple I made that generic on the
class.
It's true that in this formulation you can't do certain customized
defaulting and checking operations except by programming at the
metaclass level. However, making those two functions generic on the
instance still wouldn't make those operations simple and easy to explain
(see mail discussion of the past few months), and I think at some point
we have to limit the ambitions of CLOS and say that it doesn't replace
all forms of programming.
That's why I proposed it the way I did. This is not to say that no one
should propose that it work a different way, if they can refute the
arguments above. For this purpose, default-initargs and check-initargs
should be discussed separately.
∂03-Sep-87 1414 Bobrow.pa@Xerox.COM Re: Another try on object creation
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 3 Sep 87 14:14:21 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 03 SEP 87 14:14:38 PDT
Date: 3 Sep 87 14:14 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Another try on object creation
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 2 Sep 87 23:13 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870903-141438-10242@Xerox>
Patrick Asked
Why don't you use a class prototype to call
default-initargs and check-initargs?
Moon had two arguments for this
One is that this was the only use of prototypes,
so by changing this we can eliminate the
need to expose that concept; it makes the standard simpler.
The concept of class-prototype must be introduced for other reasons in
the metaobject protocol, so I don't buy this reason.
The second reason is ... functions generic on the class are
part of the metaclass protocol and you only write methods for them
if you are doing over part of the implementation.
My intuition (expressed in our initial propposal) was that
default-initargs, check-initargs etc were really user (instance)
business. However, I now agree with Moon that these mechanisms for
initialization (except for user-defined :after methods) are more closely
associated with the implementation of a class and hence are metaclass
methods. Ordinary users would rarely want to change them -- especially
if these methods are not guaranteed to be called each time (i.e.
optimized away) except at some great cost. Since I think these
optimizations are important in the standard case, I am happy to leave
default-initargs and check-initargs specialized on the metaclass.
I do have another question on the initialization proposal though. Why
do we need &method-key? Why not make the congruence rules for generic
functions be those Moon described for &method-key i.e. the acceptable
named arguments for a generic function are the union of the named
arguments of the methods, or &allow-other-keys. The one feature this
eliminates is the ability to define a generic function for which all
methods must have exactly the same named arguments. This seems a small
loss, and we gain by not having to add another lambda-keyword.
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
∂03-Sep-87 1705 kempf%hplabsz@hplabs.HP.COM Re: Solutions to Name/Object Mapping for Generic Functions
Received: from [15.255.16.7] by SAIL.STANFORD.EDU with TCP; 3 Sep 87 17:04:47 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Tue, 1 Sep 87 16:00:08 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 1 Sep 87 15:59:35 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 1 Sep 87 17:00:18 pdt
To: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
Cc: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Solutions to Name/Object Mapping for Generic Functions
In-Reply-To: Your message of Thu, 27 Aug 87 15:05:47 -0500.
<2766081947-606167@Jenner>
Date: Tue, 01 Sep 87 17:00:15 MST
Message-Id: <3994.557535615@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
> THE PROBLEM AND PROPERTIES OF A GOOD SOLUTION
>
>
> The following are some possible solutions:
>
> 1) The symbol function cell could be eliminated as a global object and
> the name to funcallable object mapping could be maintained within the
> environment, as is the case in Scheme.
>
> 2) The generic function slot accessor functions could take an
> environment argument and return information accordingly. This
> was the solution I believe Patrick proposed.
> 3) We could simply leave it up to implementors to supply these
> hooks, if they so choose.
> If you are talking about name-to-generic-function mapping, 2 is not what
> I have proposed.
Yes, you are right. What I should have said is that it is *similar* to
what you proposed. The original proposal mentioned modifying ADD-METHOD,
GET-METHOD, REMOVE-METHOD, FIND-APPLICABLE-METHODS, and
ENSURE-GENERIC-FUNCTION to take environment arguments, which are all part
of the metaclass protocol, in addition to SYMBOL-FUNCTION:
> 2- CLOS functions that must have an environment argument:
>
> CLASS-NAMED and its SETF form,
> ADD-METHOD,
> GET-METHOD,
> REMOVE-METHOD,
> FIND-APPLICABLE-METHODS,
> ENSURE-GENERIC-FUNCTION.
I believe the intention was, however, that they should pass the
environment on to SYMBOL-FUNCTION or use it in some implementation
dependent manner.
What 2 is proposing is to decouple modification of SYMBOL-FUNCTION to
take an environment parameter, which I believe will have serious
reprecussions for Common Lisp semantics, from the metaclass protocol
modifications. Modification of SYMBOL-FUNCTION would be the essense of
1.
> Name-to-generic-function mapping shouldn't depend on
> the metaclass protocol since it should behave the same as
> name-to-regular-function.
If SYMBOL-FUNCTION is modified to take an environment argument, then
the name-to-regular-function mapping is going to change too. A
metacircular definition of the Common Lisp interpreter might look like;
(cond
<other things>
( (fboundp (first form))
(apply (symbol-function (first form)) argument-list)
)
<more other things>
)
Changing SYMBOL-FUNCTION means this becomes;
(cond
<other things>
( (fboundp (first form))
(apply (symbol-function (first form) <environment>) argument-list)
)
<more other things>
)
But what environment? The current one? The base one? Modification of
SYMBOL-FUNCTION means that semantics of function application in Common
Lisp must be changed, becoming more like Scheme. Now, I have no objection
to this (in fact, I think it would be an improvement) but some compiler
writers and application developers might. Note that this semantic change
is very different from the one generic functions introduce, because it
involves global (environment) rather than local (parameter classes)
information, and hence could require larger modifications to existing
code.
> Not being affected by the metaclass protocol,
> it can be left to the implementation. The hook should be specified
> though. If some implementations decide to ignore the environment,
> that's fine. Since the environment is going to be passed explicitly (see
> Moon's reponse to my proposal), we either need a new primitive for that,
> or change SYMBOL-FUNCTION to accept an environment argument. A new
> primitive for metaclass programmers is probably the best thing to do.
I'm not quite sure what the "or" is here. I understand the proposal for
primitives to access the environment, but I don't understand where
the hook could be, other than through the metaclass method lambda lists.
A way to work around this difficulty might be the following. Instead of
modifying the name to generic function mapping to be sensitive to the
environment, we modify the generic function object to slot value mapping
to use the environment. This was supposed to be the essence of 2. Thus
information on methods being compiled can be stored in the generic function
object, but invocation of the generic function would get definitions
in the compiler's run time environment. This complicates the object to
slot value mapping somewhat, but avoids the problem with changing the
semantics of SYMBOL-FUNCTION. The idea is that the generic function
remembers the environment in which it was defined for funcalling purposes,
and otherwise uses the current environment for maintaining information
about definitions being compiled. Admittedly, this is a halfway solution,
but would involve less drastic modifications to Common Lisp, I think.
> However I object to 3 since it will make serious metaclass programming
> non portable.
It will restrict the class of object-object oriented languages which
can be portably implemented using the metaclass protocol to those which don't
require information on methods being compiled to be portably available
in the compile time environment. Note that CommonObjects is in this class,
and we have gotten around the problems by some monumental kludges and
some portable importabilities, ie., things which each implementor of
PCL needed to customize to their system. That particular part of
CommonObjects on CommonLoops was the most difficult to do, and the
one which breaks most often. The tradeoff for CLOS is that the metaclass
protocol would be simpler, and no modification of the base Common Lisp
semantics would be needed, meaning we could probably converge on a solution
more quickly.
∂03-Sep-87 1838 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Another try on object creation
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 3 Sep 87 18:37:57 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 227853; Thu 3-Sep-87 21:39:00 EDT
Date: Thu, 3 Sep 87 21:38 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870903-141438-10242@Xerox>
Message-ID: <870903213846.9.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 3 Sep 87 14:14 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
I'll answer the rest of your message later, because I want to think a bit,
but the answer to this question is that functions defined with defmethod
receive their arguments in exactly the same way as functions defined with
defun. So it does whatever CLtL says and the implementation implements.
∂04-Sep-87 1058 Bobrow.pa@Xerox.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 87 10:58:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 87 08:56:41 PDT
Date: 4 Sep 87 08:56 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 01 Sep 87
23:17 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870904-085641-11164@Xerox>
Dick and I had a discussion about with-added-methods. We came to the
following conclusion about handling Case 3.
(with-added-methods <generic-function> (<methods>*) . <body>)
This takes a generic function and a list of methods specified as
lambda-expressions, creates a copy of the generic function and extends
it by adding the given methods. Within the lexical scope of the form,
(in <body>) appearances of <generic-function> refer to the extended
generic-function. with-added-methods does not affect the original
definition of <generic-function>.
This answers my question --
(defmethod fie (x) 0)
(defun foo (x)
(with-added-methods fie ((lambda ((x P1)) 17))
(cons (fie x) (fum x)))
(defun fum (y) (fie y))
(foo (make-instance 'P1)) ==> (17 . 0)
And it answers Pavel's query:
During the time that WITH-ADDED-METHODS is active, should the
other processes see the added methods or not? I would hope not!
Correct.
To obtain a special version of print with added methods, one uses
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
#'print)
and passes the returned generic function as an argument. Note that
since the generic function is copied on entry, this specialized print is
not affected by later global changes to the print generic function.
∂04-Sep-87 1112 Lanning.pa@Xerox.COM WITH-SLOTS, "virtual" slots, and the meta-object protocol
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 4 Sep 87 11:12:21 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 04 SEP 87 11:10:36 PDT
Date: 4 Sep 87 11:10 PDT
Sender: Lanning.pa@Xerox.COM
From: Stanley's Tool Works <Lanning.pa@Xerox.COM>
Subject: WITH-SLOTS, "virtual" slots, and the meta-object protocol
To: Common-Lisp-Object-System@Sail.Stanford.edu
Message-ID: <870904-111036-11421@Xerox>
Start with the standard x/y v rho/theta example:
(defclass position () (x y))
(defmethod rho ((p position)) ...)
(defmethod theta ((p position)) ...)
(defmethod-setf rho ((p position)) (value) ...)
(defmethod-setf theta ((p position)) (value) ...)
What if a user of the POSITION class writes the following method:
(defmethod zoom ((p position) n)
(with-slots (p)
(setf rho (* n rho))))
How is this going to work? Presumably the WITH-SLOTS macro consults the
class to find out what vars should be treated as slot references, but
the notion that RHO and THETA are slots has not been made explicit. How
does the writer of the POSITION class tell the class about these
"virtual" slots? Perhaps there should be macros that let you write
(defaccessor rho ((p position)) ...)
(defaccessor-setf rho ((p position)) ...)
or maybe a new method-qualifier so you could write
(defmethod rho :accessor ((p position)) ...)
(defmethod-setf rho :accessor ((p position)) ...)
I guess there could also be another class-option added to DEFCLASS, but
even if there were, something like these macros would be needed.
----- smL
∂08-Sep-87 1221 RPG WITH-ADDED-METHODS
To: common-lisp-object-system@SAIL.STANFORD.EDU
There is, I think, a better syntax for WITH-ADDED-METHODS
than what Danny sent out. That syntax was one we discussed
in the context of a slightly different semantics.
(with-added-methods ((foo (...)...)
(bar (...) ...)
(bar (...) ...)
(foo (...)...)
<body>)
This takes the possibly already existing generic functions, FOO and BAR,
copies them, adds the new methods to them as specified, and then
executes <body>.
If no generic function exists, it is created. Previously defined generic
functions are not altered by the action of this construct.
The bindings of FOO and BAR have indefinite extent.
-rpg-
∂09-Sep-87 1124 Bobrow.pa@Xerox.COM Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 87 11:24:45 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 87 11:20:17 PDT
Date: 9 Sep 87 11:20 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Updating Obsolete Instances
To: common-lisp-object-system@SAIL.STANFORD.EDU
cc: Bobrow.pa@Xerox.COM
Message-ID: <870909-112017-15101@Xerox>
One of the open questions we should resolve next week is what the
protocol should be for updating obsolete instances (instances of
obsolete classes). I present here a radically simpler proposal than the
ones we were most recently considering, though it bears strong
resemblance to some that were discussed earlier.
Proposal:
A class becomes obsolete when it is redefined (directly or indirectly),
the instance slots it specifies changes, AND it has one or more
instances. For classes that are instances of standard-class, we support
a protocol to update instances whose structure becomes obsolete.
If a class becomes obsolete, then we say its instances are obsolete
instances. Let c-new be the class specified by the new class definition.
Let obsolete-slots be the names of those slots that are not included in
the new definition, added-slots be the names of the new slots added, and
common-slots be the rest.
Effectively what happens is that all the obsolete instances become a
subclass of a newly defined class that has as direct-superclasses
(obsolete-class c-new). Hence, all methods applicable to instances of
the new class are applicable to the old instances.
However, the first time an attempt is made to access a slot-value of the
obsolete instance, the structure of the instance is updated to the
current structure before the slot-value completes. The updating is done
(effectively) as follows:
1) Values of all slots in the old instance are saved
2) The structure of the instance is made to correspond to the structure
specified by the current class definition (and it is an instance of
class c-new)
3) Values of all common-slots are inserted in the new instance structure
in the same named slot
4) The generic function obsolete-instance-updated is called. Its
arguments are the instance (now with the new structure) and a property
list containing the names and values of the obsolete-slots. There is a
method on standard-object for obsolete-instance-updated
(defmethod obsolete-instance-updated
((updated-instance standard-object) obsolete-slot-values)
...)
This method initializes (from initform) any slot in the new structure
that is not already bound. Slots without initforms are not touched.
Note that by specializing obsolete-instance-updated, one can do work
before or after, or instead of the initialization of unbound slots.
To enable users to cause instances to be updated without having to add a
phony slot, or some other abomination, we provide a generic-function:
(make-class-obsolete class)
with a method for standard-class that has the appropriate effect.
DISADVANTAGES
1) This proposal specifies that updating will not happen until a slot is
accessed. Perhaps this is too restrictive on implementations.
2) Methods applicable to the old class, but no longer current are not
usable.
3) This proposal does not support sequential updating of a chain of
obsolete structures. The only information it provides is the set of
obsolete-slots and values. We could make it possible to determine which
version of the obsolete class was involved in the update by passing the
obsolete-class as a second argument to updating-obsolete-instance. But
I don't think this is worth it.
ADVANTAGES
1) It specifies exactly when the update will happen, and hence is
guaranteed to minimize the work done; that is, no instance is updated
until it needs to be. It is possible to test if an instance is obsolete
by checing its type (seeing if its class is a subclass of
obsolete-class).
2) It ameliorates a problem we were discussing about how long what
methods must be kept around etc. No old versions of methods are kept.
3) It is simple to explain. Only one instance and class is involved in
updating-obsolete-instance, and the obsolete-slot information is passed
explicitly. The default behavior is what I claim is usually wanted.
∂09-Sep-87 1630 Bobrow.pa@Xerox.COM Re: proposed syntactic cleanups in defmethod
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 9 Sep 87 16:30:24 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 09 SEP 87 16:30:51 PDT
Date: 9 Sep 87 16:30 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: proposed syntactic cleanups in defmethod
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Thu, 20 Aug 87 12:29 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870909-163051-15667@Xerox>
I propose that the DEFMETHOD macro be specified to "refer to"
(in the sense of CLtL p.160) each specialized parameter.
I think this is a fine idea.
One of the most common mistakes of beginning Lisp programmers
is omitting quote marks or putting them in the wrong place.
Actually, it's not only beginning programmers who do this. I still
do it myself sometimes, and I believe I have seen Danny Bobrow do
it.
I never do 'that'', do I??
The other problem with methods on individuals is that the
current syntax [for defmethod] is awkward when the individual is
anything other
than a symbol or a number
The intent was that for other cases, one would use the add-method form
which evaluates its arguments. However, I don't at all mind seeing a
change that makes defmethod easier to use for this case. And I agree
that evaluating the argument is useful, and using single quote may be a
more error prone as a syntax than a fully spelled keyword.
Of EQL and MEMBER, I prefer EQL since the form (MEMBER X) looks too easy
to extend with a Y and Z. But I would prefer not to suggest extensions
unless we are prepared to follow through on them soon. For this reason
some other word might be better. How about
(THIS x) as being mnemonic and short.
I think that adding QUOTE as a type-specifier to Common Lisp is
both unnecessary and confusing. (Yes, I know I suggested it. I
was wrong.) Instead, the parameter-specializer for a method on an
individual should be (MEMBER object), the type-specifier that
Common Lisp already defines for this purpose. Note that there is
no particular reason why the parameter-specializer should be the
same as the parameter-specializer-name; they're already not the
same for methods on classes.
A problem with this may be that the type specifier is used in the
specializers argument of add-method, and again this could lead to
unwarranted extrapolation. On the other hand, if you are using
add-method perhaps you are immune to unwarranted speculation.
∂09-Sep-87 2114 Moon@STONY-BROOK.SCRC.Symbolics.COM User control of the CPL
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 9 Sep 87 21:14:10 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 230758; Wed 9-Sep-87 22:43:07 EDT
Date: Wed, 9 Sep 87 22:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: User control of the CPL
To: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870909224238.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Should we adopt the :component-order class-option from Flavors, as a
simple way for the user to have control of the CPL without making him
write his own algorithm?
Gregor doesn't like the ability to specify constraints on the
ordering of classes that only apply conditionally, i.e. if those
classes are actually present among the superclasses. He considers
this bad style. Moon volunteered to write a proposal with some
examples, and we agreed to resolve this over the mail.
PROPOSAL:
The :precedence option to defclass is written (:precedence C1 C2 C3 ...)
where the C's are class names. This specifies that C1 must precede C2
in the CPL, C2 must precede C3, etc. This defclass option may appear
any number of times.
The default if no :precedence option is specified for a class C with
direct superclasses C1, C2, ..., Cn is (:precedence C C1 C2 ... Cn). To
completely eliminate all precedence constraints, specify (:precedence C).
In the notation used on page 1-14 of 87-002, the :precedence option
allows direct control over Rc. Each ordered pair (C1,C2) in Rc is
specified by writing (:precedence C1 C2). :precedence with more than
two class names is simply a convenient abbreviation for multiple
:precedence options.
OPTIONS:
Optionally we could add an additional requirement that each Ci in a
:precedence option in the defclass for C must be either C or one of C's
direct superclasses. I am opposed to this, for reasons which should
become clear from the examples. It doesn't hurt to have extra ordered
pairs in Rc that do not affect the CPL. Another way of saying this is
that the :precedence option is useful both for relaxing the precedence
constraints, compared with the default, and for adding additional
constraints to the default constraints.
Optionally we could add an additional stipulation that regardless of the
use of :precedence options, a class always precedes its direct
superclasses. Specifically, in (defclass C (C1 C2 C3) () ...), the
effect of (:precedence C C1), (:precedence C C2), and (:precedence C C3)
is always present; in addition, if the user does not specify a
:precedence option, defclass supplies (:precedence C1 C2 C3). This
would slightly simplify the following section, but it seems like a
kludgey restriction on how much control over the precedence relations
the user is permitted. I have found applications that would not work
with this restriction, so I oppose adding this restriction.
Optionally we could add a restriction that a :precedence option in the
defclass for C may not specify that another class precedes C. Flavors
has such a restriction, however I believe it to be unnecessary and I
oppose making this restriction in CLOS.
EFFECT ON CPL ALGORITHM:
The first and third paragraphs on page 1-15 of 87-002 would need to be
changed. The statement "there can be only one such candidate class" is
no longer true once the user can relax the constraints using the
:precedence option. A more complex disambiguation rule is necessarily
required. I suggest replacing the first paragraph on 1-15 with:
Sometimes there are several classes from Sc with no predecessors. In
this case, we select one of these candidate classes according to the
following rule: Traverse the superclasses of each member of the CPL
found so far, associating the number (d*n*n)-(i*n)+b with the class at
depth d and breadth b in the tree rooted at the ith element of the CPL
found so far (make it a tree by considering only the first occurrence
in breadth-first order of each class). n is the number of classes
involved (the initial length of Sc). Choose the candidate with the
smallest associated number, considering the minimum if several numbers
are associated with one class. This algorithm selects a unique
candidate because no two associated numbers are equal.
A class is always the first element of its own CPL. Thus the CPL
computed so far, used in the above rule, can never be empty. This
implies an additional check: when computing the CPL of C, if (C',C) is
an element of R, signal an error reporting that it is invalid for C'
to precede C.
The above rule is the simplest rule I could find that is compatible with
the 87-002 rule. Other rules I considered were not compatible with the
87-002 rule and had additional undesirable properties. Note that in all
cases when the :precedence option is not used this rule produces the
same answer as the one in 87-002, and produces it in essentially the
same way. In this case d=1 for the winning candidate.
There are more efficient implementations than computing all the numbers
and then finding the minimum number, however that's the easiest way I could
find to explain it. An actual implementation could traverse all the trees
in parallel, in a suitable order, and take the first candidate it encounters.
Note that the last sentence in the first paragraph on 1-15 is irrelevant
to the paragraph and repeats what was already said in the last paragraph
on 1-14, so I would simply remove it.
The third paragraph on 1-15 could be replaced with a more precise
specification of the rule quoted above, if desired.
EXAMPLES:
For brevity I have omitted from R all pairs involving the class t.
;Two superclasses and we don't care about their order
;CPL=(example2 example super-2 super-1 t)
;R={(example-2,example),(example,super-1),(example,super-2),(super-2,super-1)}
(defclass example (super-1 super-2) ()
(:precedence example super-1)
(:precedence example super-2))
(defclass example-2 (example super-2 super-1) ())
;Two mixins that can be used separately but they interact and therefore
;if they are used together, they must be used in a certain order to work.
;Specifically, mixin-2 must be before mixin-1.
(defclass base-class () ())
(defclass use-1 (mixin-1 base-class) ())
(defclass use-2 (mixin-2 base-class) ())
(defclass use-both (mixin-1 mixin-2 base-class) ())
(defclass use-both-2 (use-1 use-2) ())
(defclass mixin-1 (base-class) ()
(:precedence mixin-2 mixin-1 base-class))
(defclass mixin-2 (base-class) ()
(:precedence mixin-2 mixin-1 base-class))
;use-1 and use-2 will not accidentally include the other mixin
;use-both will get an error for inconsistent precedence constraints
;use-both-2 will get a CPL of (use-both-2 use-1 use-2 mixin-2 mixin-1 base-class t)
;R={(use-both-2,use-1),(use-1,use-2),(use-1,mixin-1),(mixin-1,base-class),
; (use-2,mixin-2),(mixin-2,base-class),(mixin-2,mixin-1)}
;"Gross example" that helped me shoot down various other rules for
;resolving topological sort ambiguities
;CPL is (a c b e d t)
;R is {(a,b),(b,d),(c,b),(e,d)}.
(defclass a (b d) ())
(defclass b (c) ()
(:precedence b))
(defclass c () ()
(:precedence c b))
(defclass d (e) ()
(:precedence d))
(defclass e () ()
(:precedence e d))
;Two examples taken from actual (ugh, bletch) window code:
;This one shows two mixins that have an ordering constraint among them,
;but are not always used together. Rather than rely on any class that
;includes both to specify the constraint correctly, we specify it here.
;The user is adding more constraints to the default constraints.
(DEFCLASS DONT-SELECT-WITH-MOUSE-MIXIN (ESSENTIAL-WINDOW) ()
;; If TV:SELECT-MIXIN is present, we must
;; override its :NAME-FOR-SELECTION method
(:PRECEDENCE TV:DONT-SELECT-WITH-MOUSE-MIXIN
TV:SELECT-MIXIN
TV:ESSENTIAL-WINDOW))
;This one shows a class that is just a bundle of useful mixins, but doesn't
;want to constrain the order of those mixins.
;The user is specifying fewer than the default constraints
(DEFCLASS WINDOW (STREAM-MIXIN BORDERS-MIXIN LABEL-MIXIN SELECT-MIXIN
GRAPHICS-MIXIN MINIMUM-WINDOW) ()
;; The mixins already come with almost all necessary constraints.
;; Relax the constraints that would normally be implied by the above list
;; of components, so that subclasses of WINDOW can rearrange things.
;; Put the label inside the border.
(:PRECEDENCE BORDERS-MIXIN LABEL-MIXIN)
;; For esthetics, force WINDOW to precede MINIMUM-WINDOW
(:PRECEDENCE WINDOW MINIMUM-WINDOW))
∂10-Sep-87 1101 kempf%hplabsz@hplabs.HP.COM Meeting on Sept. 17-18
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 11:01:20 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 10 Sep 87 10:57:15 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 10 Sep 87 08:44:19 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 10 Sep 87 09:48:14 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Meeting on Sept. 17-18
X-Mailer: mh6.5
Date: Thu, 10 Sep 87 09:48:11 MST
Message-Id: <4135.558287291@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Has the location of the meeting next week been resolved? If so, could
someone post the place and time? Thanks.
jak
PS: Our phone connection in Andover was down for about a week, so
apologies if this information has already been posted.
∂10-Sep-87 1250 Bobrow.pa@Xerox.COM Re: Meeting on Sept. 17-18
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 12:50:19 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 10 SEP 87 12:50:44 PDT
Date: 10 Sep 87 12:50 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Meeting on Sept. 17-18
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 10 Sep 87
09:48:11 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: common-lisp-object-system@sail.stanford.edu
Message-ID: <870910-125044-16719@Xerox>
Jim,
The meeting will be at Xerox, starting at 9AM on Sept 17. Come to the
visitors entrance, and ask for me or Gregor. We will have some coffee,
juice and pastries in the room, as well as a recording whiteboard.
danny
∂10-Sep-87 2248 kempf%hplabsz@hplabs.HP.COM Trace Proposal (Version 2)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 10 Sep 87 22:47:54 PDT
Received: from hplms2 by hplabs.HP.COM with TCP ; Thu, 10 Sep 87 19:54:27 pdt
Received: from hplabsz.hpl.hp.com by hplms2; Thu, 10 Sep 87 13:12:34 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Thu, 10 Sep 87 14:16:56 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Trace Proposal (Version 2)
X-Mailer: mh6.5
Date: Thu, 10 Sep 87 14:16:53 MST
Message-Id: <7309.558303413@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
Here is an updated draft of the debugging proposal. The proposal is on two
levels, a "command language" level for interactive use and a "metaobject
level" for implementation and easy language extension. The command language
level consists of the TRACE macro, for causing information
about the execution of funcallable objects to be displayed. The metaobject
level consists of a generic function, TRACE-EXECUTION,
for arranging, in an implementation dependent manner,
that this information be displayed. Note that the TRACE macro definition
is slightly incompatible with CLtL, since only one funcallable object at a
time can be specified. This was included to facilitate addition of
a :BREAK option, which, as Moon pointed out in his reply to the
original posting, would have been difficult with the original.
The CLtL UNTRACE macro would also be modified.
With regard to Moon's suggestion that the function-spec's are similar
to the proposed documentation or definition type, Larry Masinter indicated
that we should go ahead independently. However, I like the suggestion,
and have therefore modified the TRACE specification
to refer to the documentation type. In the event that no modification
of the current CLtL specification of documentation types is forthcoming
(or is delayed), the current one should be sufficient with
the addition of documentation types for CLOS entities and any for
implementation dependent tracable items (e.g. local functions).
This is noted in addition.
With regard to Moon's question about whether the following sequence:
(defun foo () ...)
(setq f #'foo)
(trace foo)
(funcall f)
generates trace output, the answer is, no. The intent of the
proposal is that when TRACE is used with a symbol as a function spec,
then invocations of the function are only traced when the function
is invoked via the definition in that symbol's global function cell.
Similarly, when TRACE-EXECUTION is called with a symbol and no
optional environment parameter, tracing occurs only when invocation
is through the symbol's global function cell. Implementations
may choose to provide tracing when a function is invoked through
application of the function definition object directly, or, as in the
case above, when the function definition is applied under another
name. In such an implementation, the above example could be rewritten
as:
(defun foo () ...)
(setq f #'foo)
(trace (function (symbol-function 'foo)))
(funcall f)
or the TRACE-EXCEUTION generic function could be called:
(trace-execution (symbol-function 'foo))
Thus, if an implementation is unable to support tracing through
the function definition object, the implementor could chose to
not support the FUNCTION function spec.
I hope we can discuss this at next week's meeting, if perhaps only
briefly in case there is not much time.
jak
Font information: UPPERCASE indicates bold, *word* indicates italics
--------------------------------------------------------------------------------
>>>>>>>>>>>>>
Addition to 87-002
>>>>>>>>>>>>>
TRACE *{function-spec}* &KEY (:BREAK NIL) *[Macro]*
UNTRACE *{function-spec}* *[Macro]*
Invoking TRACE with a function specification causes the
function specified to be traced. Henceforth whenever a specified
function is invoked, information about the call, the arguments passed,
and the returned values, if any, will be printed to the stream that is
the value of *TRACE-OUTPUT*. If the keyword argument :BREAK is T,
then the BREAK function will be called after the trace information
is printed. UNTRACE causes printing of trace information for the
specified function to cease.
A *function-spec* is either a symbol naming a function (i.e. a symbol
whose global function cell is bound to a function definition object)
or a list whose first element is a documentation type, and
whose tail indicates which particular function of that type should
be traced. Documentation types are described in the description of
the DOCUMENTATION function. The complete set of documentation types,
and thus *function-specs*, will necessarily be implementation dependent,
however, here are several *function-specs* which every implementation is
required to support:
*symbol*-Invocation of the function named by *symbol* via. *symbol*'s
global function cell are traced.
(SETF *symbol* )-If the generalized variable reference indicated by
*symbol* is tracable, then invocations of the function implementing
the SETF operation will be traced.
(METHOD *generic-function-name* *parameter-specializer-name-list*)-
If the method whose parameter specializer list and generic function
name indicated is tracable, then invocations through the generic
function name will be traced.
(MACRO-FUNCTION *symbol*)-If *symbol* has a global macro function definition,
then invocations of the macro function through *symbol* will be traced.
Some *function-specs* which may be available in particular implementations
are:
(LOCAL-FUNCTION *symbol* *environment*)-Invocations of the lexically
defined function named *symbol* defined in *environment* are traced.
(LOCAL-MACRO-FUNCTION *symbol* *environment*)-Invocations of the lexically
defined macro named *symbol* defined in *environment* are traced.
(FUNCTION *function-definition-object*)-Invocations of the function
definition object are traced, regardless of whether through the global
function definition cell in a symbol or by direct application of the
function definition object.
Implementations are encouraged to provide for tracing as many kinds
of funcallable objects as possible.
>>>>>>>>>>>>>
Additions to the List of Documentation Types on pg. 440 of CLtL:
>>>>>>>>>>>>>
METHOD - returns documentation for methods defined with DEFMETHOD.
MACRO-FUNCTION - returns documentation for macros defined with DEFMACRO.
LOCAL-FUNCTION - returns documentation for functions defined with
FLET or LABELS.
LOCAL-MACRO-FUNCTION - returns documentation for macros defined with
MACROLET.
>>>>>>>>>>>>>
Addition to 87-003
>>>>>>>>>>>>>
TRACE-EXECUTION *object* &OPTIONAL *env* &KEY (:BREAK NIL) *[Generic Function]*
TRACE-EXECUTION discriminates on *object* to select an implementation
specific method that arranges for the executable entity associated
with *object* to be traced. The optional *env* environment parameter is for
those implementations which require environmental information to
arrange for tracing to occur. Implementations are required to provide
TRACE-EXECUTION as the system level entry point for implementing TRACE
functionality. If the :BREAK keyword argument is T, arrangement is made for
the BREAK function to be called after trace information is printed.
The exact nature and number of methods associated with TRACE-EXECUTION
will differ, depending on what function specifications are supported
by TRACE, but every implementation needs to support the following
methods:
SYMBOL-The function indicated by the symbol will be traced when invoked
in the environment. If the symbol names a function which is a globally
defined macro and no environment parameter is passed, then tracing will
occur when the global macro function is invoked. If the function definition
is bound to the symbol's global function definition cell and no environment
parameter is passed, then invocations of the function via. its global
name will be traced. If an environment argument is passed, then the symbol
is taken to name a local function or local macro function and only
invocations when the environment is the same as the environment parameter
will be traced, provided the implementation can arrange for it.
METHOD-The method function is traced when invoked.
GENERIC-FUNCTION-The generic function is traced when the discriminator
code is invoked.
Some methods which may be available in particular implementations
are:
FUNCTION-Invocation of the function is traced, regardless
of whether invocation is through a named symbol.
Implementations are encouraged to provide as many methods as is possible.
∂11-Sep-87 0827 skeene@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 08:27:40 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231837; Fri 11-Sep-87 11:28:56 EDT
Date: Fri, 11 Sep 87 11:28 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870820131023.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Message-ID: <870911112819.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
I have updated my file of miscellaneous decisions taken or to be taken,
based on mail received in response to the last time I mailed this out
(two weeks ago). If anyone doesn't see their response included, or
thinks their favorite issue is missing, please let me know and I will
apologize for my error and add it.
p2-19 Values: I thought we agreed that all top level forms should return
the object. It says here defclass "returns the name of the class"
p2-22 Same comment as 2-19, for defgeneric-options
2-24 ditto for defgeneric-options-setf
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
We did decide this, and the document file reflects it. When I was
making these changes, I noticed that the only top-level form that
doesn't fit this model very well is DEFINE-METHOD-COMBINATION. I think
it should return the name of the type of method combination, not the the
object that represents the type of method combination. Programmers
never use method-combination object; they always use its name. The
reason we decided that DEFCLASS should return the class object (and so
on) is because the class object is useful. But the object representing
a method combination type is an implementation detail, and not useful to
the programmer.
I'd like to propose that we make an exception in this case, and have
DEFINE-METHOD-COMBINATION return the name of the method combination
type.
∂11-Sep-87 1023 Moon@STONY-BROOK.SCRC.Symbolics.COM Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 10:23:23 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231942; Fri 11-Sep-87 13:24:41 EDT
Date: Fri, 11 Sep 87 13:24 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870911112819.1.SKEENE@JUNCO.SCRC.Symbolics.COM>
Message-ID: <870911132423.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Fri, 11 Sep 87 11:28 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Date: Thu, 20 Aug 87 13:10 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
In July we decided to return the object for all CLOS defxxx functions (being
inconsistent with Common Lisp, but consistent within CLOS). The document file
has been updated.
We did decide this, and the document file reflects it. When I was
making these changes, I noticed that the only top-level form that
doesn't fit this model very well is DEFINE-METHOD-COMBINATION. I think
it should return the name of the type of method combination, not the the
object that represents the type of method combination. Programmers
never use method-combination object; they always use its name. The
reason we decided that DEFCLASS should return the class object (and so
on) is because the class object is useful. But the object representing
a method combination type is an implementation detail, and not useful to
the programmer.
I'd like to propose that we make an exception in this case, and have
DEFINE-METHOD-COMBINATION return the name of the method combination
type.
The real problem here is that there is no object that represents a type
of method combination. In other words, the meta-object protocol does not
directly model method combination. Perhaps a meta-object theorist can
suggest how to fix this. Otherwise, I agree that DEFINE-METHOD-COMBINATION
should return the name.
∂11-Sep-87 1034 skeene@STONY-BROOK.SCRC.Symbolics.COM short form of define-method-combination
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 10:34:19 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 231964; Fri 11-Sep-87 13:35:32 EDT
Date: Fri, 11 Sep 87 13:34 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: short form of define-method-combination
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911133455.2.SKEENE@JUNCO.SCRC.Symbolics.COM>
The following text came from Moon's message on Miscellaneous Decisions:
----------
2-26 I believe that short form method combination ought to be a macro
in the standard library, and documented there, not in the basic
principles. I think the standard combinations :append, :and, :or, ...
should also be put in the standard library too.
Kempf agrees. Moon can't have an opinion until he knows what this
library is and whether it's going to be as much of a joke as the
Common Lisp Yellow Pages.
----------
It's not clear to me who suggested putting the short form of
DEFINE-METHOD-COMBINATION into the library, but I strongly disagree
with the idea.
The short form of DEFINE-METHOD-COMBINATION satisfies the design goal of
"providing simple ways to do simple things". Many, probably most, of
the commonly-needed types of method combination can be defined that way,
with one line of code.
The way I see it, CLOS is organized in two levels.
The Programmer Interface is sufficient for most programmers to do most
things they need to do. The Meta-Object protocol lets programmers do
almost anything they could ever want to do, but it requires extra
effort. Many aspects of the programmer interface are just convenience
features, in that the programmer could achieve the same effect, with
greater effort, using the Meta-object operators. However, the
programmer interface is here because it makes CLOS much more usable.
Similarly, DEFINE-METHOD-COMBINATION has two levels -- the short form
and the long form. The short form is just a convenience feature for
the long form, but it makes declarative method combination much more
usable. I don't see any advantage in removing it from the CLOS
standard.
∂11-Sep-87 1154 Bobrow.pa@Xerox.COM [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 11:53:58 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 11:48:09 PDT
Date: 11 Sep 87 11:47 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: [kempf%hplabsz@hplabs.HP.COM: Re: Updating Obsolete Instances ]
To: common-lisp-object-system@sail.stanford.edu
Message-ID: <870911-114809-18010@Xerox>
To: Danny Bobrow <Bobrow.pa>
Subject: Re: Updating Obsolete Instances
X-Mailer: mh6.5
In-Reply-To: Your message of 09 Sep 87 11:20:00 -0700.
<870909-112017-15101@Xerox>
Date: Thu, 10 Sep 87 18:14:39 MST
Message-Id: <9967.558317679@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
General comments: This proposal seems to simplify class changing
and instance updating considerably. It is certainly the simplest
and most direct proposal advanced so far, and reduces the amount
of overhead for class changing.
> A class becomes obsolete when it is redefined (directly or indirectly),
> the instance slots it specifies changes, AND it has one or more
> instances. For classes that are instances of standard-class, we support
> a protocol to update instances whose structure becomes obsolete.
If the class has no instances, does it simply become undefined?
Assuming this is so, it should be added to the spec. Also,
need the change class protocol be applied to a class in which none
of the slot definitions have changed?
> Effectively what happens is that all the obsolete instances become a
> subclass of a newly defined class that has as direct-superclasses
> (obsolete-class c-new). Hence, all methods applicable to instances of
> the new class are applicable to the old instances.
Very nice! This would take care of the problem of how to have the methods
applicable for the new class do the updating without impacting method
invocation performance on new instances, nor requiring classes to keep
pointers to all instances created.
> However, the first time an attempt is made to access a slot-value of the
> obsolete instance, the structure of the instance is updated to the
> current structure before the slot-value completes. The updating is done
> (effectively) as follows:
> 1) Values of all slots in the old instance are saved
> 2) The structure of the instance is made to correspond to the structure
> specified by the current class definition (and it is an instance of
> class c-new)
> 3) Values of all common-slots are inserted in the new instance structure
> in the same named slot
> 4) The generic function obsolete-instance-updated is called. Its
> arguments are the instance (now with the new structure) and a property
> list containing the names and values of the obsolete-slots. There is a
> method on standard-object for obsolete-instance-updated
> (defmethod obsolete-instance-updated
> ((updated-instance standard-object) obsolete-slot-values)
> ..)
> This method initializes (from initform) any slot in the new structure
> that is not already bound. Slots without initforms are not touched.
What about a change in allocation type? For example, if the old
class had a slot whose allocation was :INSTANCE and the new :CLASS,
then does SLOT-VALUE on this slot return the new :CLASS allocated
value? If so, then DEFCLASS or OBSOLETE-INSTANCE-UPDATED should at least warn
the user that the allocation type has changed. Similarly for an
old :CLASS allocation changing to :INSTANCE. Also, if the :TYPE option
is used to type a new slot with a type which is incompatible with
the old, the user should be warned.
> To enable users to cause instances to be updated without having to add a
> phony slot, or some other abomination, we provide a generic-function:
> (make-class-obsolete class)
> with a method for standard-class that has the appropriate effect.
Yes, this is definitely needed.
> DISADVANTAGES
> 2) Methods applicable to the old class, but no longer current are not
> usable.
I don't quite understand this. What do you mean by "current"?
> 3) This proposal does not support sequential updating of a chain of
> obsolete structures. The only information it provides is the set of
> obsolete-slots and values.
Since updating is hookable, users can do this themselves if they want.
Another disadvantage is that methods which use WITH-SLOTS will
still have references to slots which no longer exist, although
attempting to reference those slots will cause the instance to
update itself. But this will also be true if the slot accessor functions
are used directly, since they will be undefined when the new class
is defined without the old slots.
An additional problem is that the obsolete classes will remain hanging
around even after all the instances are updated, unless they and the
update methods are keeping track of the number of instances around,
and they can undefine themselves once all instances are updated.
Note this won't require them to keep track of instances, just the
number created.
Looking at the semantic difficulties section on pg. 2-9 for CHANGE-CLASS,
the difficulties with changing an instance inside a method seem to
be eliminated, since, although the class changes, all methods
applicable before the change are still applicable afterwards, since
the class precedence list is only being shortened from the more
specialized end. This means that the effective method calculation
need not be redone. Problems with optimizing slot access will
still occur, but the specification for WITH-SLOTS should probably
indicate that optimization at level 3 will not remove access
through the SLOT-VALUE function unless safety is also set to 0.
Finally, it would probably be a good idea to drastically limit what the
user can do with an obsolete class, like not letting the user create an
instance of it directly. Should the user be allowed to cause an obsolete class
to become current again? My general inclination is to say probably
not. This would drift into undo-like facilites, which are best left
to the programming environment. Also, it would definitely not be
a good idea to allow use of the obsolete class as a parameter
specializer, nor to inherit from it, otherwise the semantic difficulties
with methods could recur, since the set of applicable methods and
effective method might change during method application.
----- End Forwarded Messages -----
danny
∂11-Sep-87 1154 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 11:54:06 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 11:48:45 PDT
Date: 11 Sep 87 11:48 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Updating Obsolete Instances
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Thu, 10 Sep 87
18:14:39 MST
To: common-lisp-object-system@sail.stanford.edu
cc: Bobrow.pa@Xerox.COM,kempf%hplabsz@hplabs.HP.COM
Message-ID: <870911-114845-18011@Xerox>
> A class becomes obsolete when it is redefined (directly or
> indirectly), the instance slots it specifies changes,
> AND it has one or more instances. For classes that are
> instances of standard-class, we support a protocol
> to update instances whose structure becomes obsolete.
If the class has no instances, does it simply become undefined?
No, it simply becomes redefined. The only reason to obsolete a class is
so that instances can be updated. One can radically redefine a class
that has no instances, and no obsolete class need be created.
What about a change in allocation type? For example, if the old
class had a slot whose allocation was :INSTANCE and the new :CLASS,
then does SLOT-VALUE on this slot return the new :CLASS allocated
value?
Changing an aloocation from :instance to :class of course makes a class
obsolete (if it has instances). This was supposed to be covered by the
phrase "the instance slots it specifies changes". Simlarly for the
change the other way. SLOT-VALUE on this slot should return the new
:CLASS allocated value in any methods.
DEFCLASS or OBSOLETE-INSTANCE-UPDATED should at least warn the
user that the allocation type has changed.
I don't understand the general Common Lisp policy about warnings. When
should DEFCLASS warn? Does DEFUN warn when it is redefining a function?
I don't think OBSOLETE-INSTANCE-UPDATED should ever warn, since clearly
this is dominated by the warning about change of the class.
Also, if the :TYPE option is used to type a new slot with a
type which is incompatible with the old, the user should be warned.
This need not cause a class to be obsoleted. It might cause the
accessors to be updated if they are the ones that check the type.
We do need to decide if an error is signalled if
(sef (slot-value ...)...)
tries to violate a type restriction.
> DISADVANTAGES
> 2) Methods applicable to the old class, but no longer current
> are not usable.
I don't quite understand this. What do you mean by "current"?
I was referring to an earlier discussion where it was suggested that
methods that were applicable to old instances, but have since been
changed or deleted be kept for use with the now obsolete instances. For
example, if the definition of point changed from using x and y, to using
rho and theta, the method that computed rho would no longer be needed
(should be replaced by a simple accessor). Would the old computation be
kept around. I am answering this with a NO.
Another disadvantage is that methods which use WITH-SLOTS will
still have references to slots which no longer exist, although
attempting to reference those slots will cause the instance to
update itself. But this will also be true if the slot accessor
functions are used directly, since they will be undefined when the
new class is defined without the old slots.
I think this is intrinsic to any redefinition of a class.
An additional problem is that the obsolete classes will remain
hanging around even after all the instances are updated, unless
they and the update methods are keeping track of the number of
instances around, and they can undefine themselves once all
instances are updated. Note this won't require them to keep track
of instances, just the number created.
This might be handled by the garbage collector. If there is no pointer
maintained from a superclass to an obsolete subclass, and obsolete
classes have no name, then the only pointers to the obsolete class will
be in the instances. When there are no more instances, the obsolete
class will be collected.
Looking at the semantic difficulties section on pg. 2-9 for
CHANGE-CLASS
I did not propose that this protocol for obsoleteinstances replace the
CHANGE-CLASS protocol. I have always thought it a mistake to confound
these two cases. For CHANGE-CLASS, both the classes involved are still
current (not obsolete), and hence a CLASS-CHANGED method can be called.
The difficulties with changing an instance inside a method seem
to be eliminated, since, although the class changes, all methods
applicable before the change are still applicable afterwards, since
the class precedence list is only being shortened from the more
specialized end.
For CHANGE-CLASS, the user can change an instance of any class to any
other (e.g. from a window to an automobile) and the only guaraneed
intersection of the class precedence list is OBJECT.
Problems with optimizing slot access will still occur, but the
specification for WITH-SLOTS should probably indicate that
optimization at level 3 will not remove access through the
SLOT-VALUE function unless safety is also set to 0.
There are numerous problems with fully optimized slot-value calls. In
another message I propose a protocol to deal with this problem.
Finally, it would probably be a good idea to drastically limit
what the user can do with an obsolete class, like not letting the
user create an instance of it directly. Should the user be allowed
to cause an obsolete class to become current again? My general
inclination is to say probably not. This would drift into
undo-like facilites, which are best left to the programming
environment. Also, it would definitely not be a good idea to allow
use of the obsolete class as a parameter specializer, nor to
inherit from it, otherwise the semantic difficulties with methods
could recur, since the set of applicable methods and effective
method might change during method application.
I agree. Obsolete classes should resist all changes including
production of new instances. This probably requires an
obsolete-metaclass as well as an obsolete-class to implement cleanly.
∂11-Sep-87 1204 skeene@STONY-BROOK.SCRC.Symbolics.COM proposal for arguments for call-next-method
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 12:04:35 PDT
Received: from JUNCO.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 232100; Fri 11-Sep-87 15:05:48 EDT
Date: Fri, 11 Sep 87 15:05 EDT
From: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>
Subject: proposal for arguments for call-next-method
To: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911150510.5.SKEENE@JUNCO.SCRC.Symbolics.COM>
Character-Type-Mappings: (1 0 (NIL 0) (NIL :ITALIC NIL) "CPTFONTI")
Fonts: CPTFONT, CPTFONTI
In July we agreed that call-next-method should take arguments. I
gathered together information from the various messages and came up with
the following text, which I propose should go into the CALL-NEXT-RECORD
section in Chapter 2. This text doesn't deal with other issues about
CALL-NEXT-METHOD, such as the dynamic extent or CALL-NEXT-METHOD-OR-NIL
issues.
--------------------
When {\bf call-next-method} is called with no arguments, it passes the
current method's original arguments to the next method. Neither
argument defaulting, nor using {\bf setq}, nor rebinding variables with
the same names as parameters of the method affects the values {\bf
call-next-method} passes to the method it calls.
When {\bf call-next-method} is called with arguments, the next method is
called with those arguments. When providing arguments to {\bf
call-next-method}, the following rule must be satisfied or an error is
signalled: The set of methods applicable for a changed set of arguments
for {\bf call-next-method} must be the same as the set of applicable
methods for the original arguments to the method.ε1 ε0 If {\bf call-next-method}
is called with arguments but omits optional arguments, the next method
defaults those arguments. Optimizations of the error checking are possible
but they should be invisible to the programmer.
∂11-Sep-87 1314 Bobrow.pa@Xerox.COM Deoptimizing Slot Access
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 13:14:06 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 13:14:37 PDT
Date: 11 Sep 87 13:14 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Deoptimizing Slot Access
To: Common-Lisp-Object-System@Sail.stanford.edu
cc: Bobrow.pa@Xerox.COM
Message-ID: <870911-131437-18190@Xerox>
The metaclass protocol provides for a mechanism whereby implementations
can optimize slot access for instances of certain classes. This
protocol is discussed in another message. This message is concerned
with a related problem.
Suppose we have
(defclass c1 () (x y))
and
(defmethod m1 ((i c1)) (slot-value i 'x))
and the latter method is compiled so that slot-access is optimized.
The suppose we define:
(defclass c2 (c1)
((x :allocation :special))
(:metaclass special-class))
where for classes with metaclass special-class, slot access for slots
with allocation :special it is inappropriate to use the optimized code.
Then in order to make method m1 usable for instances of class c2, it
would be nice to be able to cause a trap in the optimized code for
accessing that slot for instances of c2. We propose that there be a
standard way to cause this to happen for methods originally defined on
instances of standard class, and that the trap call
slot-value-using-class.
We propose two generic functions in the metaobject protocol associated
with this behaviour. The contract for each and the methods for
standard-class are described below:
deoptimize-slot-accesses (class slotd)
Calling this generic-function on an instance <class> of
standard-class and <slotd> of standard-slot-description will ensure
that, in any method applicable to instances of <class>, all accesses to
the slot described by <slotd> in <class> will call
slot-value-using-class. If this is not possible for these arguments, an
error is signalled.
For standard-class, an error will be signalled only if slotd is not a
slot in the class.
can-deoptimize-slot-accesses-p (class slot-description)
Returns T if deoptimize-slot-access will not signal an error.
This facility could be used to implement the cahnge in access when a
slot allocation is changed for a particular slot from :instance in a
superclass to :class in a subclass.
Methods specialized on classes are recorded. If one allows slot access
to be optimized for uses of with-slots in functions not specialized on a
class, then all such uses must be recorded so that they can be found by
deoptimize-slot-accesses.
∂11-Sep-87 1335 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 13:35:44 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 13:35:19 PDT
Date: 11 Sep 87 13:35 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Wed, 9 Sep 87 22:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870911-133519-18239@Xerox>
If we wanted to have an additional mechanism for controlling the set of
pairs in partial order that determines the class precedence list, then I
suppose this proposal is a reasonable one. However, after looking at
the examples, I felt that the gain in potential simplicity for people
who wanted to exert indirect control over the class precedence list is
more than offset by the extremely nonintuitive (to me) behaviors that
are possible to obtain from this yet another programming language.
The example for the window system would better be done by a special
program that knows how to construct window classes out of descriptions
of desired behaviors. Assuming that users know an entire complex of
class names but not about constraints among class use seems an
inappropriate intermediate position. Naive users who want to construct
a mix and match window class ought to be given a mini-expert system to
help, because constraints can easily be more than those simply
resolvable by class ordering.
∂11-Sep-87 1447 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: User control of the CPL
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 11 Sep 87 14:47:24 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 232298; Fri 11-Sep-87 17:42:39 EDT
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: User control of the CPL
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870911-133519-18239@Xerox>
Message-ID: <870911174243.1.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a special
program that knows how to construct window classes out of descriptions
of desired behaviors.
I don't see why the fact that the Zetalisp window system is badly designed
should be a design criterion for CLOS. I only included those examples
because for me it was a convenient source of examples drawn from a real
program.
∂11-Sep-87 1641 @RELAY.CS.NET:DUSSUD%Jenner@TI-CSL.CSNET Re: Updating Obsolete Instances
Received: from RELAY.CS.NET by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:41:05 PDT
Received: from relay2.cs.net by RELAY.CS.NET id ah03509; 11 Sep 87 19:25 EDT
Received: from ti-csl by RELAY.CS.NET id ah01016; 11 Sep 87 19:18 EDT
Received: from Jenner by tilde id AA08017; Fri, 11 Sep 87 17:42:43 CDT
Message-Id: <2767387349-12962022@Jenner>
Date: Fri, 11 Sep 87 17:42:29 CDT
From: Patrick H Dussud <DUSSUD%Jenner%ti-csl.csnet@RELAY.CS.NET>
To: common-lisp-object-system@SAIL.STANFORD.EDU
Subject: Re: Updating Obsolete Instances
In-Reply-To: Msg of 9 Sep 87 11:20 PDT from Danny Bobrow <Bobrow.pa@xerox.com>
If a class becomes obsolete, then we say its instances are obsolete
instances. Let c-new be the class specified by the new class definition.
Let obsolete-slots be the names of those slots that are not included in
the new definition, added-slots be the names of the new slots added, and
common-slots be the rest.
I am confused here. Are you giving up the fact that c-new is eql to the
class object existing just before the redefinition?
Effectively what happens is that all the obsolete instances become a
subclass of a newly defined class that has as direct-superclasses
(obsolete-class c-new). Hence, all methods applicable to instances of
the new class are applicable to the old instances.
I am confused here too. Do you mean that obsolete-class does not have
any method applicable to it?
3) This proposal does not support sequential updating of a chain of
obsolete structures. The only information it provides is the set of
obsolete-slots and values. We could make it possible to determine which
version of the obsolete class was involved in the update by passing the
obsolete-class as a second argument to updating-obsolete-instance. But
I don't think this is worth it.
I think that supporting sequential update is important. With machines
able to run weeks instead of hours without running out of memory or
crashing, people will want to redefine existing classes without having
to think about the ten previous updates while writing their
obsolete-instance-updated method.
∂11-Sep-87 1657 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:57:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 16:57:55 PDT
Date: 11 Sep 87 16:57 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 17:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-165755-1193@Xerox>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a
special program that knows how to construct window classes out
of descriptions of desired behaviors.
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon
I don't see why the fact that the Zetalisp
window system is badly designed should be a design criterion for
CLOS. I only included those examples because for me it was a
convenient source of examples drawn from a real program.
I did not mean to criticize the window system design (I didn't think you
were defending it). It was a good example to show how constraints
between classes might arise naturally.
But I don't think that complex constructions of that kind (even for a
well designed system) can or should be mediated by a very simple set of
ordering constraints. If there are only one or two extra ordering
constraints, then combined classes that embody the combined order
constraint in the superclass order will do, and if it is more complex
than that, then a real interactive system for construction from parts
would be more appropriate, I think.
∂11-Sep-87 2030 Bobrow.pa@Xerox.COM Re: User control of the CPL
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 16:57:37 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 16:57:55 PDT
Date: 11 Sep 87 16:57 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: User control of the CPL
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 17:42 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-165755-1193@Xerox>
Date: 11 Sep 87 13:35 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
The example for the window system would better be done by a
special program that knows how to construct window classes out
of descriptions of desired behaviors.
Date: Fri, 11 Sep 87 17:42 EDT
From: David A. Moon
I don't see why the fact that the Zetalisp
window system is badly designed should be a design criterion for
CLOS. I only included those examples because for me it was a
convenient source of examples drawn from a real program.
I did not mean to criticize the window system design (I didn't think you
were defending it). It was a good example to show how constraints
between classes might arise naturally.
But I don't think that complex constructions of that kind (even for a
well designed system) can or should be mediated by a very simple set of
ordering constraints. If there are only one or two extra ordering
constraints, then combined classes that embody the combined order
constraint in the superclass order will do, and if it is more complex
than that, then a real interactive system for construction from parts
would be more appropriate, I think.
∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Updating Obsolete Instances
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:39 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 17:52:06 PDT
Date: 11 Sep 87 17:52 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Updating Obsolete Instances
In-reply-to: Patrick H Dussud <DUSSUD%Jenner@ti-csl.CSNET>'s message of
Fri, 11 Sep 87 17:42:29 CDT
To: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911-175206-1258@Xerox>
If a class becomes obsolete, then we say its
instances are obsolete instances. Let c-new be the class
specified by the new class definition. Let obsolete-slots be
the names of those slots that are not included in the new
definition, added-slots be the names of the new slots added,
and common-slots be the rest.
I am confused here. Are you giving up the fact that c-new is
eql to the class object existing just before the redefinition?
No. I should have been more explicit. c-new is EQL to the original
class, but has the new description.
Effectively what happens is that all the obsolete
instances become a subclass of a newly defined class that has
as direct-superclasses (obsolete-class c-new). Hence, all
methods applicable to instances of the new class are
applicable to the old instances.
I am confused here too. Do you mean that obsolete-class does
not have any method applicable to it?
The only method on obsolete-class that I know about is
slot-value-using-class, and it causes the updating to happen.
3) This proposal does not support sequential updating
of a chain of obsolete structures. The only information it
provides is the set of obsolete-slots and values. We could
make it possible to determine which version of the obsolete
class was involved in the update by passing the obsolete-class
as a second argument to updating-obsolete-instance. But I
don't think this is worth it.
I think that supporting sequential update is important. With
machines able to run weeks instead of hours without running out of
memory or crashing, people will want to redefine existing classes
without having to think about the ten previous updates while
writing their obsolete-instance-updated method.
I am not convinced that people would really use this. My model is that
they would continue to edit the obsolete-instance-updated each time if
there was significant work to do; and most of the time the obsolete
instances would probably not be used, even if the classes changed often.
But of course I am flaming about "usual programming practice". For
Loops, we had the simplest version of this feature (it always just saved
obsolete slot values on a property list), and we had no complaints. I
often ran in the same image for a week or two at a time, doing extensive
development.
∂11-Sep-87 2057 Bobrow.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 17:41:24 PDT
Date: 11 Sep 87 17:41 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:24 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870911-174124-1245@Xerox>
I'd like to propose that we make an exception in this
case, and have DEFINE-METHOD-COMBINATION return the name of
the method combination type.
The real problem here is that there is no object that
represents a type of method combination. In other words, the
meta-object protocol does not directly model method combination.
Perhaps a meta-object theorist can suggest how to fix this.
Otherwise, I agree that DEFINE-METHOD-COMBINATION should return the
name.
As a representative of the meta-theorist camp, I want to agree that the
appropriate thing to return in this case is the name.
danny
∂11-Sep-87 2058 Bobrow.pa@Xerox.COM Re: short form of define-method-combination
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 11 Sep 87 20:57:50 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 11 SEP 87 18:45:11 PDT
Date: 11 Sep 87 18:45 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: short form of define-method-combination
In-reply-to: Sonya E. Keene <skeene@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:34 EDT
To: skeene@STONY-BROOK.SCRC.Symbolics.COM
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870911-184511-1302@Xerox>
It's not clear to me who suggested putting the short form of
DEFINE-METHOD-COMBINATION into the library, but I strongly disagree
with the idea.
I cannot tell a lie. It was I.
The short form of DEFINE-METHOD-COMBINATION satisfies the
design goal of "providing simple ways to do simple things". Many,
probably most, of the commonly-needed types of method combination
can be defined that way, with one line of code.
Are there other simple cases other than ones that are predefined e.g.
:and :append ...? I thought you had already defined the useful ones
(REF Symbolic manual).
The Programmer Interface is sufficient for most programmers to
do most things they need to do.
I am suggesting that a library that is first class (it consists of
standard implementations of useful things) be included with the
standard. The rule should be, if an implementation includes a feature
like this (has the same name) it should be equivalent to this one.
Library programs would be straightforward programming excercises for
some of the less frequently used programming tools. In addition to
DEFINE-METHOD-COMBINATION in the short form, I would put in there
functions like
all-class-slot-names class &optional allocation
and other simple uses of mapcar over some of the basic data structures.
We can even add something like classes to implement active values, slot
properties, dynmaic slots, and a few other of the features that we took
out of the standard but a significant number of users seem to be
reinventing.
I don't see any advantage in removing it from the CLOS
standard.
The advantage I see is that it allows us another level beyond the basic
programmer's interface. There is a three level structure
1) Metaobject protocol (fine grain control of the implementmentation)
2) Programmers Interface (what I use everyday)
3) Programmer's library (Useful things I might do on accasion)
If we can make level 3 real for CLOS (meaning it is as standardized as
the spec -- but is in a library), perhaps we can even push this idea
into Common Lisp itself.
∂14-Sep-87 1346 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 13:46:33 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 13:43:33 PDT
Date: 14 Sep 87 13:43 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Fri, 11 Sep 87 13:24 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-134333-2880@Xerox>
Well, if you believe that define-method-combination expands something
like this:
(define-method-combination AND ..) ==>
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
(type (eql 'and))
..)
..)
Then the appropriate object would be the method on
compute-effective-method-internal or whatever the name of the generic
function the following method is documented to call.
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
..)
(compute-effective-method-internal
generic-function
(slot-value generic-function 'method-combination-type)
..))
∂14-Sep-87 1439 Bobrow.pa@Xerox.COM Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 14:39:42 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 14:39:45 PDT
Date: 14 Sep 87 14:39 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Uninitialized Slots
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-143945-2999@Xerox>
Moon noted:
2-19 uninitialized slots should be an error to reference, not
be defined to return an unstandardized value with no error. I'm
willing not to require that it signals an error if people feel that
would be an undue burden, otherwise I prefer that reading an
uninitialized slot signals an error.
In July we decided that signalling an error here should
depend on the declared safety level.
Rather than signal an error directly, I propose that a generic-function
be called, dependent in the same way on safetty level:
slot-uninitialized (class instance slot-name)
where class is the class of the instance. The method on standard-class
signals an error. Among other things, this allows an easy implementation
of default values in classes, a current feature of Loops, Strobe and
KEE.
∂14-Sep-87 1446 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Miscellaneous decisions taken or to be taken
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 14:46:16 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233579; Mon 14-Sep-87 17:47:10 EDT
Date: Mon, 14 Sep 87 17:47 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Miscellaneous decisions taken or to be taken
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-134333-2880@Xerox>
Message-ID: <870914174715.5.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 13:43 PDT
From: Gregor.pa@Xerox.COM
Well, if you believe that define-method-combination expands something
like this:
(define-method-combination AND ..) ==>
(defmethod compute-effective-method-internal
((generic-function standard-generic-function)
(type (eql 'and))
..)
..)
Then the appropriate object would be the method on
compute-effective-method-internal or ....
I disagree. That method object is -part of the implementation of- the
method combination type, but it does not -represent- the method
combination type in the same sense that a class object -represents- a
class and a method object -represents- a method, in the meta-object
world's -model- of what the system is doing. Switching to speaking
operationally from speaking philosophically, there aren't operations on
that method object that will tell you things about the
method-combination type. If I'm wrong here then I -really- don't
understand meta-objects (which is of course possible).
∂14-Sep-87 1510 Gregor.pa@Xerox.COM Re: Miscellaneous decisions taken or to be taken
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:10:47 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 15:11:01 PDT
Date: 14 Sep 87 15:10 PDT
From: Gregor.pa@Xerox.COM
Subject: Re: Miscellaneous decisions taken or to be taken
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 14 Sep 87 17:47 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-151101-3059@Xerox>
No, I think you are right, that method object doesn't really represent
the method combination type. I was kind of kidding.
BUT, if as part of a particular implementation, you decided to store the
information which "represents" the method combination type as some
datastructure rather than just having it be 'inline' in the code of the
method; storing it in the method object might be reasonable.
That sentence is contorted, but what I mean is that both of the
following expansioons for define-method-combination are reasonable:
(define-method-combination :FOO ..)
(defmethod mumble (..)
(let ((info (GET ':FOO 'METHOD-COMBINATION-TYPE)))
...)))
(let ((method (make-instance 'dmc-method ...)))
(setf (method-function method)
#'(lambda (..)
(let ((info (SLOT-VALUE METHOD 'INFO))) ..)))
(add-method #'mumble method))
Of course in the second example, the stuff stored inside the method is
just a "random" structure in the same way the stuff stored on the plist
is. I am just trying to show that the documented existence of the
method object can be used like this to hold the structure. This also
make it possible for the GC to collect that "random structure" if the
method is dropped on the floor.
∂14-Sep-87 1511 Moon@STONY-BROOK.SCRC.Symbolics.COM Uninitialized Slots
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:11:45 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233609; Mon 14-Sep-87 18:12:28 EDT
Date: Mon, 14 Sep 87 18:12 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Uninitialized Slots
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-143945-2999@Xerox>
Message-ID: <870914181233.3.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 14:39 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Moon noted:
2-19 uninitialized slots should be an error to reference, not
be defined to return an unstandardized value with no error. I'm
willing not to require that it signals an error if people feel that
would be an undue burden, otherwise I prefer that reading an
uninitialized slot signals an error.
In July we decided that signalling an error here should
depend on the declared safety level.
Rather than signal an error directly, I propose that a generic-function
be called, dependent in the same way on safetty level:
slot-uninitialized (class instance slot-name)
where class is the class of the instance. The method on standard-class
signals an error. Among other things, this allows an easy implementation
of default values in classes, a current feature of Loops, Strobe and
KEE.
I'm happy with this. I'll edit it into the document from which "Moon noted"
came (I hope tonight to mail out the last version of that document before
this week's meeting).
∂14-Sep-87 1532 kempf%hplabsz@hplabs.HP.COM Re: User control of the CPL
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:31:05 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Mon, 14 Sep 87 15:25:16 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Mon, 14 Sep 87 15:52:50 pdt
To: "David A. Moon" <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: User control of the CPL
X-Mailer: mh6.5
In-Reply-To: Your message of Wed, 09 Sep 87 22:42:00 -0400.
<870909224238.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: Mon, 14 Sep 87 15:52:46 MST
Message-Id: <4795.558654766@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> The default if no :precedence option is specified for a class C with
> direct superclasses C1, C2, ..., Cn is (:precedence C C1 C2 ... Cn). To
> completely eliminate all precedence constraints, specify (:precedence C).
> In the notation used on page 1-14 of 87-002, the :precedence option
> allows direct control over Rc. Each ordered pair (C1,C2) in Rc is
> specified by writing (:precedence C1 C2). :precedence with more than
> two class names is simply a convenient abbreviation for multiple
> :precedence options.
It sounds from this that you are thinking here about controlling the
local precedence order using the :PRECEDENCE option (please correct
me if I'm wrong), but I don't think that's necessary. A user can control
the local precedence order by simply changing the order of the supers
in the super list. The problems come when trying to impose some kind of
global control over the CPL.
> Optionally we could add an additional requirement that each Ci in a
> :precedence option in the defclass for C must be either C or one of C's
> direct superclasses. I am opposed to this, for reasons which should
> become clear from the examples. It doesn't hurt to have extra ordered
> pairs in Rc that do not affect the CPL. Another way of saying this is
> that the :precedence option is useful both for relaxing the precedence
> constraints, compared with the default, and for adding additional
> constraints to the default constraints.
See comment above.
> Optionally we could add an additional stipulation that regardless of the
> use of :precedence options, a class always precedes its direct
> superclasses. Specifically, in (defclass C (C1 C2 C3) () ...), the
> effect of (:precedence C C1), (:precedence C C2), and (:precedence C C3)
> is always present; in addition, if the user does not specify a
> :precedence option, defclass supplies (:precedence C1 C2 C3). This
> would slightly simplify the following section, but it seems like a
> kludgey restriction on how much control over the precedence relations
> the user is permitted. I have found applications that would not work
> with this restriction, so I oppose adding this restriction.
I tend to think that this stipulation may be necessary, however, I'm
open to examples where it may not. From my reading of the examples
included at the end of the base note, I couldn't find any where
this stipulation would make the example not possible. The reason I think it
should be included is that I think it fits the mental model of inheritance as
specialization, which is how I think we'd like to encourage people to
think about inheritance in the default CLOS language. If people want
to use the metaobject protocol to write their own inheritance algorithm,
then they should be able to do whatever they want. People who want to
think about inheritance differently can write a CALCULATE-CLASS-PRECEDENCE
-LIST method customized to do things differently.
Also, putting in this stipulation (e.g. a class always preceeds it's
direct superclasses) reinforces the concept of local precedence order,
which means that programmers can deal with a class and its superclasses
as a kind of logical unit.
>>>>>>>>
While I'm not sure about this particular proposal, I am in favor of
some kind of user control over the CPL calculation, but for different
reasons. For the case where the inheritance graph cannot be linearized,
the user should be given the option of being able to control the
linearization and specify the global precedence ordering when conflicts
occur, without having to write a CALCULATE-CLASS-PRECEDENCE-LIST method.
Whether this control comes in the form of a continuable error when
the default algorithm fails (in which case, the user is invited to
supply a consistent list, perhaps interactively) or as a class option
in which the user supplies some global precedence constraint or some
other way is not that important, as long as it fits in well with
the rest of CLOS. Some form of control is needed, however.
Additionally, the class freezing proposal which was briefly
discussed last spring as an optimization procedure would be another
case where a user controlled the CPL calculation. In that case,
the CPL of a "frozen" class would need to be treated as a unit for
any subclass inheriting from the frozen class. The result would be
the same as a user defined constraint on the CPL, except the constraint
would be on the entire CPL of the super and not on a subsection.
There are other aspects to class freezing as well
(disallowing redefinitions for example).
It would be nice if both these needs could be united into
one, perhaps with a new generic function or macro in the user interface
section which gives the user control over the CPL (or part thereof)
in a manner consistent with the rest of the user level language, rather
than a new constraint language, but maybe that's hoping for too much.
For random changes to the CPL, I think that using the metaobject protocol
would probably be best.
jak
∂14-Sep-87 1547 Masinter.pa@Xerox.COM Re: Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 15:47:12 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 15:47:28 PDT
Date: 14 Sep 87 15:47 PDT
From: Masinter.pa@Xerox.COM
Subject: Re: Uninitialized Slots
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Mon, 14 Sep 87 18:12 EDT
To: Bobrow.pa@Xerox.COM
cc: Common-Lisp-Object-System@SAIL.STANFORD.EDU
Message-ID: <870914-154728-3159@Xerox>
There are really serious problems with having a well-defined operation
(like calling slot-uninitialized) depend on the "declared safety level".
The only things that should depend on the declared safety level are
whether an error is signalled when it "should be". Otherwise, the safety
level must enter into the language semantics rather than being just a
"hint".
∂14-Sep-87 1642 Bobrow.pa@Xerox.COM Re: Agenda for September meeting
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 16:42:23 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 16:42:35 PDT
Date: 14 Sep 87 16:42 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Agenda for September meeting
In-reply-to: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>'s
message of Tue, 18 Aug 87 14:46 EDT
To: Moon@STONY-BROOK.SCRC.Symbolics.COM
cc: Common-Lisp-Object-System@sail.stanford.edu
Message-ID: <870914-164235-3253@Xerox>
Discuss written proposals on major areas, circulated over the
network before the meeting and brought to the meeting in hardcopy.
A number of proposals have appeared over the network. How should they
appear in hardcopy. Do you intend to extract what you think are the
current proposals, or should we have distributed resposnsibility. Seems
like the latter is fairer, but we ought to have a list of the expected
proposals. Do you have a list of such proposals that need separate
write-ups? e.g.
generic-labels, with-added-methods (RPG)
obsolete instances (dgb)
object creation (dam)
call-next-method (sk)
...
To be included in misc decisions file???
1.
...
∂14-Sep-87 2058 Moon@STONY-BROOK.SCRC.Symbolics.COM Re: Agenda for September meeting
Received: from SCRC-STONY-BROOK.ARPA by SAIL.STANFORD.EDU with TCP; 14 Sep 87 20:58:01 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 233805; Mon 14-Sep-87 23:29:36 EDT
Date: Mon, 14 Sep 87 23:29 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Agenda for September meeting
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870914-164235-3253@Xerox>
Message-ID: <870914232936.0.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 14 Sep 87 16:42 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Discuss written proposals on major areas, circulated over the
network before the meeting and brought to the meeting in hardcopy.
A number of proposals have appeared over the network. How should they
appear in hardcopy. Do you intend to extract what you think are the
current proposals, or should we have distributed resposnsibility. Seems
like the latter is fairer, but we ought to have a list of the expected
proposals.
It will have to be distributed responsibility. Due to other commitments
I will not be able to do any significant amount of additional work to
prepare for the meeting. I don't think I will even be able to send out
a substantially revised version of the miscellaneous issues and
decisions file. I'd like each person who has proposed something to
bring at least one hardcopy of their proposal (I assume we can get things
copied at PARC). I'll bring hardcopies of things I have proposed and of
all the mail that I had thought was worth saving.
Do you have a list of such proposals that need separate write-ups?
Here's the list I made earlier today of issues that were discussed in the
mail since the last meeting, excluding very small issues. This covers
about 85 messages. Next to each one I put names of people who I noticed
having enough to say to count as a proposal. I may have missed some people.
Large issues are listed first, but otherwise there is no particular order.
Object Creation (Moon, possibly Gregor)
Class Redefinition (Bobrow, Moon, Dussud)
Class and Generic Function Naming (everybody?)
Local Generics, Methods (RPG)
Class Precedence (Moon, possibly RPG, possibly Kempf)
Trace (Kempf)
&key lambda-list congruence (Bobrow, Moon)
Short form of define-method-combination (Moon, Bobrow)
call-next-method with arguments (SKeene)
call-next-method closure extent (RPG)
Defmethod syntax for methods on individuals (Moon)
Virtual slots for with-slots ((Lanning))
Uninitialized Slots (Bobrow)
∂14-Sep-87 2129 Bobrow.pa@Xerox.COM Re: Names to Objects and Compiler-environment
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 14 Sep 87 21:29:11 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 14 SEP 87 17:17:19 PDT
Date: 14 Sep 87 17:17 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Names to Objects and Compiler-environment
In-reply-to: kempf%hplabsz@hplabs.HP.COM's message of Wed, 26 Aug 87
11:28:22 MST
To: kempf%hplabsz@hplabs.HP.COM
cc: DUSSUD%Jenner%ti-csl.CSNet@relay.cs.net,
common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870914-171719-3304@Xerox>
After reading the messages sent, I think that only the following very
simple name to object mapping interface should be supported.In general,
there must be (effectively) different objects in the different
environments, since objects in a compiler environment canot be allowed
to interact with the runtime objects; optimizations that minimize
copying should be invisible to the user. With this the other
generic-functions that Patrick suggested should be extended can be left
as they are.
Name To Object Generic Functions.
symbol-class symbol &optional environment
==> class or NIL
symbol-function symbol &optional environment ****
==> function or NIL
symbol-setf-function symbol &optional environment
==> function or NIL
**** Change to Common Lisp -- We should argue for it.
The generic-functions above all support setf forms:
(setf (symbol-class symbol &optional environment) class)
==> class
(setf (symbol-function symbol &optional environment) function)
==> function
(setf (symbol-setf-function symbol &optional environment) function)
==> function
If the value argument for any of these forms is NIL, then this is
equivalent to the corresponding CMAKUNBOUND, or FMAKUNBOUND ****
**** Change to Common Lisp -- We should argue for it.
For the Object to Name mapping, CLOS should provide the generic
functions:
class-name class
==> symbol
function-name function
==> symbol
These return a symbol. The return value is only considered a hint.
There is no guarantee that a symbol returned is a name for the class
(function), or if NIL is returned, the class or function does not have a
name.
∂15-Sep-87 0923 RPG Uninitialized Slots
To: common-lisp-object-system@SAIL.STANFORD.EDU
If we use Moon's proposed behavior
``In July we decided that signalling an error here should
depend on the declared safety level. ''
the proper terminology, according to my not-as-yet-adopted terminology
for error situations, is that accessing an uninitialized slot should
signal an error.
I believe Danny's proposal has the difficult-to-justify property of
encouraging users to write code whose correct behavior depends on the
safety level used during compilation. That is, if we provide a
generic function that is invoked upon some erroneous but common situation,
users will pack useful code into the methods on that function.
Danny writes:
``Rather than signal an error directly, I propose that a
generic-function be called, dependent in the same way on safety
level.... Among other things, this allows an easy
implementation of default values in classes, a current feature
of Loops, Strobe and KEE.''
-rpg-
∂15-Sep-87 0935 RPG Proposals
To: common-lisp-object-system@SAIL.STANFORD.EDU
I will bring hardcopies of my proposals. I will clean them up considerably
beforehand, but you can get the drift from the mail.
-rpg-
∂15-Sep-87 1009 kempf%hplabsz@hplabs.HP.COM Re: Proposals
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 10:09:05 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 15 Sep 87 10:05:13 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 15 Sep 87 11:09:47 pdt
To: common-lisp-object-system@sail.stanford.edu
Subject: Re: Proposals
X-Mailer: mh6.5
In-Reply-To: Your message of 15 Sep 87 09:35:00 -0700.
Date: Tue, 15 Sep 87 11:09:43 MST
Message-Id: <12363.558724183@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
>
> I will bring hardcopies of my proposals. I will clean them up considerably
> beforehand, but you can get the drift from the mail.
I'll do the same.
jak
∂15-Sep-87 1356 Bobrow.pa@Xerox.COM Re: Uninitialized Slots
Received: from XEROX.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 13:56:16 PDT
Received: from Cabernet.ms by ArpaGateway.ms ; 15 SEP 87 13:55:06 PDT
Date: 15 Sep 87 13:55 PDT
Sender: Bobrow.pa@Xerox.COM
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
Subject: Re: Uninitialized Slots
In-reply-to: Dick Gabriel <RPG@SAIL.STANFORD.EDU>'s message of 15 Sep 87
09:23 PDT
To: RPG@SAIL.STANFORD.EDU
cc: common-lisp-object-system@SAIL.STANFORD.EDU
Message-ID: <870915-135506-4468@Xerox>
If we use Moon's proposed behavior
``In July we decided that signalling an error here
should depend on the declared safety level. ''
the proper terminology, according to my not-as-yet-adopted
terminology for error situations, is that accessing an
uninitialized slot should signal an error.
I believe Danny's proposal has the difficult-to-justify
property of encouraging users to write code whose correct behavior
depends on the safety level used during compilation. That is, if we
provide a generic function that is invoked upon some erroneous but
common situation, users will pack useful code into the methods on
that function.
Given this argument, I suggest we back off on the commitment that there
can be compilation of slot-access that depends on the declared safety
level for standard instances. I propose that for standard-class the
system should ALWAYS call slot-uninitialized if an uninitialized slot is
accessed. It should be easy to build a metaclass that can provide
more optimized access for production compilation.
∂15-Sep-87 1627 kempf%hplabsz@hplabs.HP.COM Re: Updating Obsolete Instances (and CHANGE-CLASS)
Received: from HPLABS.HP.COM by SAIL.STANFORD.EDU with TCP; 15 Sep 87 16:26:27 PDT
Received: from hplabsz.hpl.hp.com by hplms2; Tue, 15 Sep 87 16:22:07 pdt
Return-Path: <kempf@hplabsz>
Received: from hplabsz by hplabsz; Tue, 15 Sep 87 17:26:39 pdt
To: Danny Bobrow <Bobrow.pa@Xerox.COM>
Cc: common-lisp-object-system@sail.stanford.edu
Subject: Re: Updating Obsolete Instances (and CHANGE-CLASS)
X-Mailer: mh6.5
In-Reply-To: Your message of 11 Sep 87 11:48:00 -0700.
<870911-114845-18011@Xerox>
Date: Tue, 15 Sep 87 17:26:36 MST
Message-Id: <15740.558746796@hplabsz>
From: kempf%hplabsz@hplabs.HP.COM
> Looking at the semantic difficulties section on pg. 2-9 for
> CHANGE-CLASS
> I did not propose that this protocol for obsolete instances replace the
> CHANGE-CLASS protocol. I have always thought it a mistake to confound
> these two cases. For CHANGE-CLASS, both the classes involved are still
> current (not obsolete), and hence a CLASS-CHANGED method can be called.
>
> The difficulties with changing an instance inside a method seem
> to be eliminated, since, although the class changes, all methods
> applicable before the change are still applicable afterwards, since
> the class precedence list is only being shortened from the more
> specialized end.
> For CHANGE-CLASS, the user can change an instance of any class to any
> other (e.g. from a window to an automobile) and the only guaraneed
> intersection of the class precedence list is OBJECT.
I was under the impression that CHANGE-CLASS was primarily there for
updating of obsolete instances. Since this proposal decouples the two,
CHANGE-CLASS/CLASS-CHANGED as currently formulated seems to be even
weaker.
I believe that user defined coercions are probably a good idea, but that they
should be integrated with the Common Lisp COERCE function (CLtL, pg.
51-52) rather than through a new function. Considering the already full
agenda for this week's meeting, I hesitate to suggest that we discuss this
(though I will come with a written up proposal, in case we have time). Both
CHANGE-CLASS and CLASS-CHANGED can be replaced by making COERCE a
generic function. The "destructive in-place modification" property which
seems to be the reason for CLASS-CHANGED can simply be the default behavior
for COERCE when called with a CLOS object. Optionally, a flag parameter could
be included to control this behavior. In any event, the semantic difficulties
mentioned in the spec and the statement "the generic function
CLASS-CHANGED is not intended to be called by the programmer" at the
beginning of the CLASS-CHANGED description seem to indicate that something
more is needed on this.
jak
∂15-Sep-87 1916 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Another try on object creation
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 15 Sep 87 19:16:07 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 163152; Tue 15-Sep-87 21:55:00 EDT
Date: Tue, 15 Sep 87 21:54 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Another try on object creation
To: Common-Lisp-Object-System@SAIL.STANFORD.EDU
In-Reply-To: <870903-141438-10242@Xerox>
Message-ID: <870915215412.7.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 3 Sep 87 14:14 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
Why
do we need &method-key? Why not make the congruence rules for generic
functions be those Moon described for &method-key i.e. the acceptable
named arguments for a generic function are the union of the named
arguments of the methods, or &allow-other-keys. The one feature this
eliminates is the ability to define a generic function for which all
methods must have exactly the same named arguments. This seems a small
loss, and we gain by not having to add another lambda-keyword.
I tried this out in the version of the proposal that I will bring to the
meeting, and it seems to work out fairly well.
Another question. What happens if a method is invoked with a named
argument that it is not prepared to receive? Is it a run-time error?
It is easy to construct examples where this could happen.
In 87-002, the answer was very simple: methods work the same as ordinary
functions in this respect, and whatever CLtL says happens, happens.
With the introduction of &method-key, that's still true when &method-key
is not used, but when &method-key is used, the situation cannot happen
because the generic-function-to-method dispatching mechanism is defined
to do the checking. With your proposal to make &key work like
&method-key, the situation you mention can never happen.
CLtL p.62 says named-argument name mismatch "is an error", so the
argument list validity checking in the generic-function-to-method
dispatching mechanism should conform to that and signal an error under
implementation-dependent control.
∂15-Sep-87 2006 Moon@SAPSUCKER.SCRC.Symbolics.COM Re: Anonymous Generic Function Proposal (Draft 2)
Received: from [128.81.41.223] by SAIL.STANFORD.EDU with TCP; 15 Sep 87 20:06:06 PDT
Received: from EUPHRATES.SCRC.Symbolics.COM by SAPSUCKER.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 163174; Tue 15-Sep-87 23:07:47 EDT
Date: Tue, 15 Sep 87 23:06 EDT
From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Re: Anonymous Generic Function Proposal (Draft 2)
To: common-lisp-object-system@SAIL.STANFORD.EDU
In-Reply-To: <870904-085641-11164@Xerox>
Message-ID: <870915230654.8.MOON@EUPHRATES.SCRC.Symbolics.COM>
Date: 4 Sep 87 08:56 PDT
From: Danny Bobrow <Bobrow.pa@Xerox.COM>
....
To obtain a special version of print with added methods, one uses
(with-added-methods #'print ((lambda (...)...) (lambda (...)...))
#'print)
and passes the returned generic function as an argument. Note that
since the generic function is copied on entry, this specialized print is
not affected by later global changes to the print generic function.
This actually brings up an interesting point. PRINT is not a generic
function, PRINT-OBJECT is. If you change this example to specify
#'print-object instead of #'print, you realize that this is fairly
useless. The documentation of print-object says that the user is not
supposed to call it; it is called automatically by the system functions
such as PRINT, WRITE, and ~S. Making a copy of print-object with some
new methods is fairly useless, since there is no way to get the system
functions to call it. This is simply one instance of a general problem
with interfaces.
I don't think any mechanism that isn't essentially equivalent to dynamic
binding of function definitions will solve this problem. I'm not convinced
that CLOS actually needs to solve this problem though.
This point is somewhat off the main track of the anonymous generic function
proposal, and I do not consider it an argument against that proposal.